XMLHttpRequest.cpp 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322
  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. #include "config.h"
  23. #include "XMLHttpRequest.h"
  24. #include "Blob.h"
  25. #include "BlobData.h"
  26. #include "ContentSecurityPolicy.h"
  27. #include "ContextFeatures.h"
  28. #include "CrossOriginAccessControl.h"
  29. #include "DOMFormData.h"
  30. #include "DOMImplementation.h"
  31. #include "Event.h"
  32. #include "EventException.h"
  33. #include "EventListener.h"
  34. #include "EventNames.h"
  35. #include "ExceptionCode.h"
  36. #include "File.h"
  37. #include "HTMLDocument.h"
  38. #include "HTTPParsers.h"
  39. #include "HistogramSupport.h"
  40. #include "InspectorInstrumentation.h"
  41. #include "JSDOMBinding.h"
  42. #include "JSDOMWindow.h"
  43. #include "MemoryCache.h"
  44. #include "ParsedContentType.h"
  45. #include "ResourceError.h"
  46. #include "ResourceRequest.h"
  47. #include "ScriptCallStack.h"
  48. #include "ScriptController.h"
  49. #include "ScriptProfile.h"
  50. #include "Settings.h"
  51. #include "SharedBuffer.h"
  52. #include "TextResourceDecoder.h"
  53. #include "ThreadableLoader.h"
  54. #include "XMLHttpRequestException.h"
  55. #include "XMLHttpRequestProgressEvent.h"
  56. #include "XMLHttpRequestUpload.h"
  57. #include "markup.h"
  58. #include <heap/Strong.h>
  59. #include <runtime/JSLock.h>
  60. #include <runtime/Operations.h>
  61. #include <wtf/ArrayBuffer.h>
  62. #include <wtf/ArrayBufferView.h>
  63. #include <wtf/RefCountedLeakCounter.h>
  64. #include <wtf/StdLibExtras.h>
  65. #include <wtf/text/CString.h>
  66. #if ENABLE(RESOURCE_TIMING)
  67. #include "CachedResourceRequestInitiators.h"
  68. #endif
  69. namespace WebCore {
  70. DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, xmlHttpRequestCounter, ("XMLHttpRequest"));
  71. // Histogram enum to see when we can deprecate xhr.send(ArrayBuffer).
  72. enum XMLHttpRequestSendArrayBufferOrView {
  73. XMLHttpRequestSendArrayBuffer,
  74. XMLHttpRequestSendArrayBufferView,
  75. XMLHttpRequestSendArrayBufferOrViewMax,
  76. };
  77. struct XMLHttpRequestStaticData {
  78. WTF_MAKE_NONCOPYABLE(XMLHttpRequestStaticData); WTF_MAKE_FAST_ALLOCATED;
  79. public:
  80. XMLHttpRequestStaticData();
  81. String m_proxyHeaderPrefix;
  82. String m_secHeaderPrefix;
  83. HashSet<String, CaseFoldingHash> m_forbiddenRequestHeaders;
  84. };
  85. XMLHttpRequestStaticData::XMLHttpRequestStaticData()
  86. : m_proxyHeaderPrefix("proxy-")
  87. , m_secHeaderPrefix("sec-")
  88. {
  89. m_forbiddenRequestHeaders.add("accept-charset");
  90. m_forbiddenRequestHeaders.add("accept-encoding");
  91. m_forbiddenRequestHeaders.add("access-control-request-headers");
  92. m_forbiddenRequestHeaders.add("access-control-request-method");
  93. m_forbiddenRequestHeaders.add("connection");
  94. m_forbiddenRequestHeaders.add("content-length");
  95. m_forbiddenRequestHeaders.add("content-transfer-encoding");
  96. m_forbiddenRequestHeaders.add("cookie");
  97. m_forbiddenRequestHeaders.add("cookie2");
  98. m_forbiddenRequestHeaders.add("date");
  99. m_forbiddenRequestHeaders.add("expect");
  100. m_forbiddenRequestHeaders.add("host");
  101. m_forbiddenRequestHeaders.add("keep-alive");
  102. m_forbiddenRequestHeaders.add("origin");
  103. m_forbiddenRequestHeaders.add("referer");
  104. m_forbiddenRequestHeaders.add("te");
  105. m_forbiddenRequestHeaders.add("trailer");
  106. m_forbiddenRequestHeaders.add("transfer-encoding");
  107. m_forbiddenRequestHeaders.add("upgrade");
  108. m_forbiddenRequestHeaders.add("user-agent");
  109. m_forbiddenRequestHeaders.add("via");
  110. }
  111. static bool isSetCookieHeader(const AtomicString& name)
  112. {
  113. return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set-cookie2");
  114. }
  115. static void replaceCharsetInMediaType(String& mediaType, const String& charsetValue)
  116. {
  117. unsigned int pos = 0, len = 0;
  118. findCharsetInMediaType(mediaType, pos, len);
  119. if (!len) {
  120. // When no charset found, do nothing.
  121. return;
  122. }
  123. // Found at least one existing charset, replace all occurrences with new charset.
  124. while (len) {
  125. mediaType.replace(pos, len, charsetValue);
  126. unsigned int start = pos + charsetValue.length();
  127. findCharsetInMediaType(mediaType, pos, len, start);
  128. }
  129. }
  130. static const XMLHttpRequestStaticData* staticData = 0;
  131. static const XMLHttpRequestStaticData* createXMLHttpRequestStaticData()
  132. {
  133. staticData = new XMLHttpRequestStaticData;
  134. return staticData;
  135. }
  136. static const XMLHttpRequestStaticData* initializeXMLHttpRequestStaticData()
  137. {
  138. // Uses dummy to avoid warnings about an unused variable.
  139. AtomicallyInitializedStatic(const XMLHttpRequestStaticData*, dummy = createXMLHttpRequestStaticData());
  140. return dummy;
  141. }
  142. static void logConsoleError(ScriptExecutionContext* context, const String& message)
  143. {
  144. if (!context)
  145. return;
  146. // FIXME: It's not good to report the bad usage without indicating what source line it came from.
  147. // We should pass additional parameters so we can tell the console where the mistake occurred.
  148. context->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message);
  149. }
  150. PassRefPtr<XMLHttpRequest> XMLHttpRequest::create(ScriptExecutionContext* context)
  151. {
  152. RefPtr<XMLHttpRequest> xmlHttpRequest(adoptRef(new XMLHttpRequest(context)));
  153. xmlHttpRequest->suspendIfNeeded();
  154. return xmlHttpRequest.release();
  155. }
  156. XMLHttpRequest::XMLHttpRequest(ScriptExecutionContext* context)
  157. : ActiveDOMObject(context)
  158. , m_async(true)
  159. , m_includeCredentials(false)
  160. #if ENABLE(XHR_TIMEOUT)
  161. , m_timeoutMilliseconds(0)
  162. #endif
  163. , m_state(UNSENT)
  164. , m_createdDocument(false)
  165. , m_error(false)
  166. , m_uploadEventsAllowed(true)
  167. , m_uploadComplete(false)
  168. , m_sameOriginRequest(true)
  169. , m_receivedLength(0)
  170. , m_lastSendLineNumber(0)
  171. , m_exceptionCode(0)
  172. , m_progressEventThrottle(this)
  173. , m_responseTypeCode(ResponseTypeDefault)
  174. {
  175. initializeXMLHttpRequestStaticData();
  176. #ifndef NDEBUG
  177. xmlHttpRequestCounter.increment();
  178. #endif
  179. }
  180. XMLHttpRequest::~XMLHttpRequest()
  181. {
  182. #ifndef NDEBUG
  183. xmlHttpRequestCounter.decrement();
  184. #endif
  185. }
  186. Document* XMLHttpRequest::document() const
  187. {
  188. ASSERT(scriptExecutionContext()->isDocument());
  189. return static_cast<Document*>(scriptExecutionContext());
  190. }
  191. SecurityOrigin* XMLHttpRequest::securityOrigin() const
  192. {
  193. return scriptExecutionContext()->securityOrigin();
  194. }
  195. #if ENABLE(DASHBOARD_SUPPORT)
  196. bool XMLHttpRequest::usesDashboardBackwardCompatibilityMode() const
  197. {
  198. if (scriptExecutionContext()->isWorkerContext())
  199. return false;
  200. Settings* settings = document()->settings();
  201. return settings && settings->usesDashboardBackwardCompatibilityMode();
  202. }
  203. #endif
  204. XMLHttpRequest::State XMLHttpRequest::readyState() const
  205. {
  206. return m_state;
  207. }
  208. String XMLHttpRequest::responseText(ExceptionCode& ec)
  209. {
  210. if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeText) {
  211. ec = INVALID_STATE_ERR;
  212. return "";
  213. }
  214. return m_responseBuilder.toStringPreserveCapacity();
  215. }
  216. Document* XMLHttpRequest::responseXML(ExceptionCode& ec)
  217. {
  218. if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeDocument) {
  219. ec = INVALID_STATE_ERR;
  220. return 0;
  221. }
  222. if (m_error || m_state != DONE)
  223. return 0;
  224. if (!m_createdDocument) {
  225. bool isHTML = equalIgnoringCase(responseMIMEType(), "text/html");
  226. // The W3C spec requires the final MIME type to be some valid XML type, or text/html.
  227. // If it is text/html, then the responseType of "document" must have been supplied explicitly.
  228. if ((m_response.isHTTP() && !responseIsXML() && !isHTML)
  229. || (isHTML && m_responseTypeCode == ResponseTypeDefault)
  230. || scriptExecutionContext()->isWorkerContext()) {
  231. m_responseDocument = 0;
  232. } else {
  233. if (isHTML)
  234. m_responseDocument = HTMLDocument::create(0, m_url);
  235. else
  236. m_responseDocument = Document::create(0, m_url);
  237. // FIXME: Set Last-Modified.
  238. m_responseDocument->setContent(m_responseBuilder.toStringPreserveCapacity());
  239. m_responseDocument->setSecurityOrigin(securityOrigin());
  240. m_responseDocument->setContextFeatures(document()->contextFeatures());
  241. if (!m_responseDocument->wellFormed())
  242. m_responseDocument = 0;
  243. }
  244. m_createdDocument = true;
  245. }
  246. return m_responseDocument.get();
  247. }
  248. Blob* XMLHttpRequest::responseBlob(ExceptionCode& ec)
  249. {
  250. if (m_responseTypeCode != ResponseTypeBlob) {
  251. ec = INVALID_STATE_ERR;
  252. return 0;
  253. }
  254. // We always return null before DONE.
  255. if (m_state != DONE)
  256. return 0;
  257. if (!m_responseBlob) {
  258. // FIXME: This causes two (or more) unnecessary copies of the data.
  259. // Chromium stores blob data in the browser process, so we're pulling the data
  260. // from the network only to copy it into the renderer to copy it back to the browser.
  261. // Ideally we'd get the blob/file-handle from the ResourceResponse directly
  262. // instead of copying the bytes. Embedders who store blob data in the
  263. // same process as WebCore would at least to teach BlobData to take
  264. // a SharedBuffer, even if they don't get the Blob from the network layer directly.
  265. OwnPtr<BlobData> blobData = BlobData::create();
  266. // If we errored out or got no data, we still return a blob, just an empty one.
  267. size_t size = 0;
  268. if (m_binaryResponseBuilder) {
  269. RefPtr<RawData> rawData = RawData::create();
  270. size = m_binaryResponseBuilder->size();
  271. rawData->mutableData()->append(m_binaryResponseBuilder->data(), size);
  272. blobData->appendData(rawData, 0, BlobDataItem::toEndOfFile);
  273. String normalizedContentType = Blob::normalizedContentType(responseMIMEType());
  274. blobData->setContentType(normalizedContentType); // responseMIMEType defaults to text/xml which may be incorrect.
  275. m_binaryResponseBuilder.clear();
  276. }
  277. m_responseBlob = Blob::create(blobData.release(), size);
  278. }
  279. return m_responseBlob.get();
  280. }
  281. ArrayBuffer* XMLHttpRequest::responseArrayBuffer(ExceptionCode& ec)
  282. {
  283. if (m_responseTypeCode != ResponseTypeArrayBuffer) {
  284. ec = INVALID_STATE_ERR;
  285. return 0;
  286. }
  287. if (m_state != DONE)
  288. return 0;
  289. if (!m_responseArrayBuffer.get() && m_binaryResponseBuilder.get() && m_binaryResponseBuilder->size() > 0) {
  290. m_responseArrayBuffer = ArrayBuffer::create(const_cast<char*>(m_binaryResponseBuilder->data()), static_cast<unsigned>(m_binaryResponseBuilder->size()));
  291. m_binaryResponseBuilder.clear();
  292. }
  293. return m_responseArrayBuffer.get();
  294. }
  295. #if ENABLE(XHR_TIMEOUT)
  296. void XMLHttpRequest::setTimeout(unsigned long timeout, ExceptionCode& ec)
  297. {
  298. // FIXME: Need to trigger or update the timeout Timer here, if needed. http://webkit.org/b/98156
  299. // 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."
  300. if (scriptExecutionContext()->isDocument() && !m_async) {
  301. logConsoleError(scriptExecutionContext(), "XMLHttpRequest.timeout cannot be set for synchronous HTTP(S) requests made from the window context.");
  302. ec = INVALID_ACCESS_ERR;
  303. return;
  304. }
  305. m_timeoutMilliseconds = timeout;
  306. }
  307. #endif
  308. void XMLHttpRequest::setResponseType(const String& responseType, ExceptionCode& ec)
  309. {
  310. if (m_state >= LOADING) {
  311. ec = INVALID_STATE_ERR;
  312. return;
  313. }
  314. // Newer functionality is not available to synchronous requests in window contexts, as a spec-mandated
  315. // attempt to discourage synchronous XHR use. responseType is one such piece of functionality.
  316. // We'll only disable this functionality for HTTP(S) requests since sync requests for local protocols
  317. // such as file: and data: still make sense to allow.
  318. if (!m_async && scriptExecutionContext()->isDocument() && m_url.protocolIsInHTTPFamily()) {
  319. logConsoleError(scriptExecutionContext(), "XMLHttpRequest.responseType cannot be changed for synchronous HTTP(S) requests made from the window context.");
  320. ec = INVALID_ACCESS_ERR;
  321. return;
  322. }
  323. if (responseType == "")
  324. m_responseTypeCode = ResponseTypeDefault;
  325. else if (responseType == "text")
  326. m_responseTypeCode = ResponseTypeText;
  327. else if (responseType == "document")
  328. m_responseTypeCode = ResponseTypeDocument;
  329. else if (responseType == "blob")
  330. m_responseTypeCode = ResponseTypeBlob;
  331. else if (responseType == "arraybuffer")
  332. m_responseTypeCode = ResponseTypeArrayBuffer;
  333. else
  334. ASSERT_NOT_REACHED();
  335. }
  336. String XMLHttpRequest::responseType()
  337. {
  338. switch (m_responseTypeCode) {
  339. case ResponseTypeDefault:
  340. return "";
  341. case ResponseTypeText:
  342. return "text";
  343. case ResponseTypeDocument:
  344. return "document";
  345. case ResponseTypeBlob:
  346. return "blob";
  347. case ResponseTypeArrayBuffer:
  348. return "arraybuffer";
  349. }
  350. return "";
  351. }
  352. XMLHttpRequestUpload* XMLHttpRequest::upload()
  353. {
  354. if (!m_upload)
  355. m_upload = XMLHttpRequestUpload::create(this);
  356. return m_upload.get();
  357. }
  358. void XMLHttpRequest::changeState(State newState)
  359. {
  360. if (m_state != newState) {
  361. m_state = newState;
  362. callReadyStateChangeListener();
  363. }
  364. }
  365. void XMLHttpRequest::callReadyStateChangeListener()
  366. {
  367. if (!scriptExecutionContext())
  368. return;
  369. InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRReadyStateChangeEvent(scriptExecutionContext(), this);
  370. if (m_async || (m_state <= OPENED || m_state == DONE))
  371. m_progressEventThrottle.dispatchReadyStateChangeEvent(XMLHttpRequestProgressEvent::create(eventNames().readystatechangeEvent), m_state == DONE ? FlushProgressEvent : DoNotFlushProgressEvent);
  372. InspectorInstrumentation::didDispatchXHRReadyStateChangeEvent(cookie);
  373. if (m_state == DONE && !m_error) {
  374. InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRLoadEvent(scriptExecutionContext(), this);
  375. m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadEvent));
  376. InspectorInstrumentation::didDispatchXHRLoadEvent(cookie);
  377. m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadendEvent));
  378. }
  379. }
  380. void XMLHttpRequest::setWithCredentials(bool value, ExceptionCode& ec)
  381. {
  382. if (m_state > OPENED || m_loader) {
  383. ec = INVALID_STATE_ERR;
  384. return;
  385. }
  386. m_includeCredentials = value;
  387. }
  388. bool XMLHttpRequest::isAllowedHTTPMethod(const String& method)
  389. {
  390. return !equalIgnoringCase(method, "TRACE")
  391. && !equalIgnoringCase(method, "TRACK")
  392. && !equalIgnoringCase(method, "CONNECT");
  393. }
  394. String XMLHttpRequest::uppercaseKnownHTTPMethod(const String& method)
  395. {
  396. if (equalIgnoringCase(method, "COPY") || equalIgnoringCase(method, "DELETE") || equalIgnoringCase(method, "GET")
  397. || equalIgnoringCase(method, "HEAD") || equalIgnoringCase(method, "INDEX") || equalIgnoringCase(method, "LOCK")
  398. || equalIgnoringCase(method, "M-POST") || equalIgnoringCase(method, "MKCOL") || equalIgnoringCase(method, "MOVE")
  399. || equalIgnoringCase(method, "OPTIONS") || equalIgnoringCase(method, "POST") || equalIgnoringCase(method, "PROPFIND")
  400. || equalIgnoringCase(method, "PROPPATCH") || equalIgnoringCase(method, "PUT") || equalIgnoringCase(method, "UNLOCK")) {
  401. return method.upper();
  402. }
  403. return method;
  404. }
  405. bool XMLHttpRequest::isAllowedHTTPHeader(const String& name)
  406. {
  407. initializeXMLHttpRequestStaticData();
  408. return !staticData->m_forbiddenRequestHeaders.contains(name) && !name.startsWith(staticData->m_proxyHeaderPrefix, false)
  409. && !name.startsWith(staticData->m_secHeaderPrefix, false);
  410. }
  411. void XMLHttpRequest::open(const String& method, const KURL& url, ExceptionCode& ec)
  412. {
  413. open(method, url, true, ec);
  414. }
  415. void XMLHttpRequest::open(const String& method, const KURL& url, bool async, ExceptionCode& ec)
  416. {
  417. internalAbort();
  418. State previousState = m_state;
  419. m_state = UNSENT;
  420. m_error = false;
  421. m_uploadComplete = false;
  422. // clear stuff from possible previous load
  423. clearResponse();
  424. clearRequest();
  425. ASSERT(m_state == UNSENT);
  426. if (!isValidHTTPToken(method)) {
  427. ec = SYNTAX_ERR;
  428. return;
  429. }
  430. if (!isAllowedHTTPMethod(method)) {
  431. ec = SECURITY_ERR;
  432. return;
  433. }
  434. // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved.
  435. bool shouldBypassMainWorldContentSecurityPolicy = false;
  436. if (scriptExecutionContext()->isDocument()) {
  437. Document* document = static_cast<Document*>(scriptExecutionContext());
  438. if (document->frame())
  439. shouldBypassMainWorldContentSecurityPolicy = document->frame()->script()->shouldBypassMainWorldContentSecurityPolicy();
  440. }
  441. if (!shouldBypassMainWorldContentSecurityPolicy && !scriptExecutionContext()->contentSecurityPolicy()->allowConnectToSource(url)) {
  442. // FIXME: Should this be throwing an exception?
  443. ec = SECURITY_ERR;
  444. return;
  445. }
  446. if (!async && scriptExecutionContext()->isDocument()) {
  447. if (document()->settings() && !document()->settings()->syncXHRInDocumentsEnabled()) {
  448. logConsoleError(scriptExecutionContext(), "Synchronous XMLHttpRequests are disabled for this page.");
  449. ec = INVALID_ACCESS_ERR;
  450. return;
  451. }
  452. // Newer functionality is not available to synchronous requests in window contexts, as a spec-mandated
  453. // attempt to discourage synchronous XHR use. responseType is one such piece of functionality.
  454. // We'll only disable this functionality for HTTP(S) requests since sync requests for local protocols
  455. // such as file: and data: still make sense to allow.
  456. if (url.protocolIsInHTTPFamily() && m_responseTypeCode != ResponseTypeDefault) {
  457. logConsoleError(scriptExecutionContext(), "Synchronous HTTP(S) requests made from the window context cannot have XMLHttpRequest.responseType set.");
  458. ec = INVALID_ACCESS_ERR;
  459. return;
  460. }
  461. #if ENABLE(XHR_TIMEOUT)
  462. // Similarly, timeouts are disabled for synchronous requests as well.
  463. if (m_timeoutMilliseconds > 0) {
  464. logConsoleError(scriptExecutionContext(), "Synchronous XMLHttpRequests must not have a timeout value set.");
  465. ec = INVALID_ACCESS_ERR;
  466. return;
  467. }
  468. #endif
  469. }
  470. m_method = uppercaseKnownHTTPMethod(method);
  471. m_url = url;
  472. m_async = async;
  473. ASSERT(!m_loader);
  474. // Check previous state to avoid dispatching readyState event
  475. // when calling open several times in a row.
  476. if (previousState != OPENED)
  477. changeState(OPENED);
  478. else
  479. m_state = OPENED;
  480. }
  481. void XMLHttpRequest::open(const String& method, const KURL& url, bool async, const String& user, ExceptionCode& ec)
  482. {
  483. KURL urlWithCredentials(url);
  484. urlWithCredentials.setUser(user);
  485. open(method, urlWithCredentials, async, ec);
  486. }
  487. void XMLHttpRequest::open(const String& method, const KURL& url, bool async, const String& user, const String& password, ExceptionCode& ec)
  488. {
  489. KURL urlWithCredentials(url);
  490. urlWithCredentials.setUser(user);
  491. urlWithCredentials.setPass(password);
  492. open(method, urlWithCredentials, async, ec);
  493. }
  494. bool XMLHttpRequest::initSend(ExceptionCode& ec)
  495. {
  496. if (!scriptExecutionContext())
  497. return false;
  498. if (m_state != OPENED || m_loader) {
  499. ec = INVALID_STATE_ERR;
  500. return false;
  501. }
  502. m_error = false;
  503. return true;
  504. }
  505. void XMLHttpRequest::send(ExceptionCode& ec)
  506. {
  507. send(String(), ec);
  508. }
  509. void XMLHttpRequest::send(Document* document, ExceptionCode& ec)
  510. {
  511. ASSERT(document);
  512. if (!initSend(ec))
  513. return;
  514. if (m_method != "GET" && m_method != "HEAD" && m_url.protocolIsInHTTPFamily()) {
  515. String contentType = getRequestHeader("Content-Type");
  516. if (contentType.isEmpty()) {
  517. #if ENABLE(DASHBOARD_SUPPORT)
  518. if (usesDashboardBackwardCompatibilityMode())
  519. setRequestHeaderInternal("Content-Type", "application/x-www-form-urlencoded");
  520. else
  521. #endif
  522. // FIXME: this should include the charset used for encoding.
  523. setRequestHeaderInternal("Content-Type", "application/xml");
  524. }
  525. // FIXME: According to XMLHttpRequest Level 2, this should use the Document.innerHTML algorithm
  526. // from the HTML5 specification to serialize the document.
  527. String body = createMarkup(document);
  528. // FIXME: this should use value of document.inputEncoding to determine the encoding to use.
  529. TextEncoding encoding = UTF8Encoding();
  530. m_requestEntityBody = FormData::create(encoding.encode(body.characters(), body.length(), EntitiesForUnencodables));
  531. if (m_upload)
  532. m_requestEntityBody->setAlwaysStream(true);
  533. }
  534. createRequest(ec);
  535. }
  536. void XMLHttpRequest::send(const String& body, ExceptionCode& ec)
  537. {
  538. if (!initSend(ec))
  539. return;
  540. if (!body.isNull() && m_method != "GET" && m_method != "HEAD" && m_url.protocolIsInHTTPFamily()) {
  541. String contentType = getRequestHeader("Content-Type");
  542. if (contentType.isEmpty()) {
  543. #if ENABLE(DASHBOARD_SUPPORT)
  544. if (usesDashboardBackwardCompatibilityMode())
  545. setRequestHeaderInternal("Content-Type", "application/x-www-form-urlencoded");
  546. else
  547. #endif
  548. setRequestHeaderInternal("Content-Type", "application/xml");
  549. } else {
  550. replaceCharsetInMediaType(contentType, "UTF-8");
  551. m_requestHeaders.set("Content-Type", contentType);
  552. }
  553. m_requestEntityBody = FormData::create(UTF8Encoding().encode(body.characters(), body.length(), EntitiesForUnencodables));
  554. if (m_upload)
  555. m_requestEntityBody->setAlwaysStream(true);
  556. }
  557. createRequest(ec);
  558. }
  559. void XMLHttpRequest::send(Blob* body, ExceptionCode& ec)
  560. {
  561. if (!initSend(ec))
  562. return;
  563. if (m_method != "GET" && m_method != "HEAD" && m_url.protocolIsInHTTPFamily()) {
  564. const String& contentType = getRequestHeader("Content-Type");
  565. if (contentType.isEmpty()) {
  566. const String& blobType = body->type();
  567. if (!blobType.isEmpty() && isValidContentType(blobType))
  568. setRequestHeaderInternal("Content-Type", blobType);
  569. else {
  570. // From FileAPI spec, whenever media type cannot be determined, empty string must be returned.
  571. setRequestHeaderInternal("Content-Type", "");
  572. }
  573. }
  574. // FIXME: add support for uploading bundles.
  575. m_requestEntityBody = FormData::create();
  576. if (body->isFile())
  577. m_requestEntityBody->appendFile(toFile(body)->path());
  578. #if ENABLE(BLOB)
  579. else
  580. m_requestEntityBody->appendBlob(body->url());
  581. #endif
  582. }
  583. createRequest(ec);
  584. }
  585. void XMLHttpRequest::send(DOMFormData* body, ExceptionCode& ec)
  586. {
  587. if (!initSend(ec))
  588. return;
  589. if (m_method != "GET" && m_method != "HEAD" && m_url.protocolIsInHTTPFamily()) {
  590. m_requestEntityBody = FormData::createMultiPart(*(static_cast<FormDataList*>(body)), body->encoding(), document());
  591. // We need to ask the client to provide the generated file names if needed. When FormData fills the element
  592. // for the file, it could set a flag to use the generated file name, i.e. a package file on Mac.
  593. m_requestEntityBody->generateFiles(document());
  594. String contentType = getRequestHeader("Content-Type");
  595. if (contentType.isEmpty()) {
  596. contentType = makeString("multipart/form-data; boundary=", m_requestEntityBody->boundary().data());
  597. setRequestHeaderInternal("Content-Type", contentType);
  598. }
  599. }
  600. createRequest(ec);
  601. }
  602. void XMLHttpRequest::send(ArrayBuffer* body, ExceptionCode& ec)
  603. {
  604. String consoleMessage("ArrayBuffer is deprecated in XMLHttpRequest.send(). Use ArrayBufferView instead.");
  605. scriptExecutionContext()->addConsoleMessage(JSMessageSource, WarningMessageLevel, consoleMessage);
  606. HistogramSupport::histogramEnumeration("WebCore.XHR.send.ArrayBufferOrView", XMLHttpRequestSendArrayBuffer, XMLHttpRequestSendArrayBufferOrViewMax);
  607. sendBytesData(body->data(), body->byteLength(), ec);
  608. }
  609. void XMLHttpRequest::send(ArrayBufferView* body, ExceptionCode& ec)
  610. {
  611. HistogramSupport::histogramEnumeration("WebCore.XHR.send.ArrayBufferOrView", XMLHttpRequestSendArrayBufferView, XMLHttpRequestSendArrayBufferOrViewMax);
  612. sendBytesData(body->baseAddress(), body->byteLength(), ec);
  613. }
  614. void XMLHttpRequest::sendBytesData(const void* data, size_t length, ExceptionCode& ec)
  615. {
  616. if (!initSend(ec))
  617. return;
  618. if (m_method != "GET" && m_method != "HEAD" && m_url.protocolIsInHTTPFamily()) {
  619. m_requestEntityBody = FormData::create(data, length);
  620. if (m_upload)
  621. m_requestEntityBody->setAlwaysStream(true);
  622. }
  623. createRequest(ec);
  624. }
  625. void XMLHttpRequest::sendFromInspector(PassRefPtr<FormData> formData, ExceptionCode& ec)
  626. {
  627. m_requestEntityBody = formData ? formData->deepCopy() : 0;
  628. createRequest(ec);
  629. m_exceptionCode = ec;
  630. }
  631. void XMLHttpRequest::createRequest(ExceptionCode& ec)
  632. {
  633. #if ENABLE(BLOB)
  634. // Only GET request is supported for blob URL.
  635. if (m_url.protocolIs("blob") && m_method != "GET") {
  636. ec = XMLHttpRequestException::NETWORK_ERR;
  637. return;
  638. }
  639. #endif
  640. // The presence of upload event listeners forces us to use preflighting because POSTing to an URL that does not
  641. // permit cross origin requests should look exactly like POSTing to an URL that does not respond at all.
  642. // Also, only async requests support upload progress events.
  643. bool uploadEvents = false;
  644. if (m_async) {
  645. m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
  646. if (m_requestEntityBody && m_upload) {
  647. uploadEvents = m_upload->hasEventListeners();
  648. m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
  649. }
  650. }
  651. m_sameOriginRequest = securityOrigin()->canRequest(m_url);
  652. // We also remember whether upload events should be allowed for this request in case the upload listeners are
  653. // added after the request is started.
  654. m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders);
  655. ResourceRequest request(m_url);
  656. request.setHTTPMethod(m_method);
  657. #if PLATFORM(BLACKBERRY)
  658. request.setTargetType(ResourceRequest::TargetIsXHR);
  659. #endif
  660. InspectorInstrumentation::willLoadXHR(scriptExecutionContext(), this, m_method, m_url, m_async, m_requestEntityBody ? m_requestEntityBody->deepCopy() : 0, m_requestHeaders, m_includeCredentials);
  661. if (m_requestEntityBody) {
  662. ASSERT(m_method != "GET");
  663. ASSERT(m_method != "HEAD");
  664. request.setHTTPBody(m_requestEntityBody.release());
  665. }
  666. if (m_requestHeaders.size() > 0)
  667. request.addHTTPHeaderFields(m_requestHeaders);
  668. ThreadableLoaderOptions options;
  669. options.sendLoadCallbacks = SendCallbacks;
  670. options.sniffContent = DoNotSniffContent;
  671. options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight;
  672. options.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
  673. options.crossOriginRequestPolicy = UseAccessControl;
  674. options.securityOrigin = securityOrigin();
  675. #if ENABLE(RESOURCE_TIMING)
  676. options.initiator = cachedResourceRequestInitiators().xmlhttprequest;
  677. #endif
  678. #if ENABLE(XHR_TIMEOUT)
  679. if (m_timeoutMilliseconds)
  680. request.setTimeoutInterval(m_timeoutMilliseconds / 1000.0);
  681. #endif
  682. m_exceptionCode = 0;
  683. m_error = false;
  684. if (m_async) {
  685. if (m_upload)
  686. request.setReportUploadProgress(true);
  687. // ThreadableLoader::create can return null here, for example if we're no longer attached to a page.
  688. // This is true while running onunload handlers.
  689. // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload, <http://bugs.webkit.org/show_bug.cgi?id=10904>.
  690. // FIXME: Maybe create() can return null for other reasons too?
  691. m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, options);
  692. if (m_loader) {
  693. // Neither this object nor the JavaScript wrapper should be deleted while
  694. // a request is in progress because we need to keep the listeners alive,
  695. // and they are referenced by the JavaScript wrapper.
  696. setPendingActivity(this);
  697. }
  698. } else {
  699. InspectorInstrumentation::willLoadXHRSynchronously(scriptExecutionContext());
  700. ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), request, *this, options);
  701. InspectorInstrumentation::didLoadXHRSynchronously(scriptExecutionContext());
  702. }
  703. if (!m_exceptionCode && m_error)
  704. m_exceptionCode = XMLHttpRequestException::NETWORK_ERR;
  705. ec = m_exceptionCode;
  706. }
  707. void XMLHttpRequest::abort()
  708. {
  709. // internalAbort() calls dropProtection(), which may release the last reference.
  710. RefPtr<XMLHttpRequest> protect(this);
  711. bool sendFlag = m_loader;
  712. internalAbort();
  713. clearResponseBuffers();
  714. // Clear headers as required by the spec
  715. m_requestHeaders.clear();
  716. if ((m_state <= OPENED && !sendFlag) || m_state == DONE)
  717. m_state = UNSENT;
  718. else {
  719. ASSERT(!m_loader);
  720. changeState(DONE);
  721. m_state = UNSENT;
  722. }
  723. m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
  724. if (!m_uploadComplete) {
  725. m_uploadComplete = true;
  726. if (m_upload && m_uploadEventsAllowed)
  727. m_upload->dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
  728. }
  729. }
  730. void XMLHttpRequest::internalAbort()
  731. {
  732. bool hadLoader = m_loader;
  733. m_error = true;
  734. // FIXME: when we add the support for multi-part XHR, we will have to think be careful with this initialization.
  735. m_receivedLength = 0;
  736. if (hadLoader) {
  737. m_loader->cancel();
  738. m_loader = 0;
  739. }
  740. m_decoder = 0;
  741. InspectorInstrumentation::didFailXHRLoading(scriptExecutionContext(), this);
  742. if (hadLoader)
  743. dropProtection();
  744. }
  745. void XMLHttpRequest::clearResponse()
  746. {
  747. m_response = ResourceResponse();
  748. clearResponseBuffers();
  749. }
  750. void XMLHttpRequest::clearResponseBuffers()
  751. {
  752. m_responseBuilder.clear();
  753. m_responseEncoding = String();
  754. m_createdDocument = false;
  755. m_responseDocument = 0;
  756. m_responseBlob = 0;
  757. m_binaryResponseBuilder.clear();
  758. m_responseArrayBuffer.clear();
  759. }
  760. void XMLHttpRequest::clearRequest()
  761. {
  762. m_requestHeaders.clear();
  763. m_requestEntityBody = 0;
  764. }
  765. void XMLHttpRequest::genericError()
  766. {
  767. clearResponse();
  768. clearRequest();
  769. m_error = true;
  770. changeState(DONE);
  771. }
  772. void XMLHttpRequest::networkError()
  773. {
  774. genericError();
  775. m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().errorEvent));
  776. if (!m_uploadComplete) {
  777. m_uploadComplete = true;
  778. if (m_upload && m_uploadEventsAllowed)
  779. m_upload->dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().errorEvent));
  780. }
  781. internalAbort();
  782. }
  783. void XMLHttpRequest::abortError()
  784. {
  785. genericError();
  786. m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
  787. if (!m_uploadComplete) {
  788. m_uploadComplete = true;
  789. if (m_upload && m_uploadEventsAllowed)
  790. m_upload->dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
  791. }
  792. }
  793. void XMLHttpRequest::dropProtection()
  794. {
  795. // The XHR object itself holds on to the responseText, and
  796. // thus has extra cost even independent of any
  797. // responseText or responseXML objects it has handed
  798. // out. But it is protected from GC while loading, so this
  799. // can't be recouped until the load is done, so only
  800. // report the extra cost at that point.
  801. JSC::VM* vm = scriptExecutionContext()->vm();
  802. JSC::JSLockHolder lock(vm);
  803. vm->heap.reportExtraMemoryCost(m_responseBuilder.length() * 2);
  804. unsetPendingActivity(this);
  805. }
  806. void XMLHttpRequest::overrideMimeType(const String& override)
  807. {
  808. m_mimeTypeOverride = override;
  809. }
  810. void XMLHttpRequest::setRequestHeader(const AtomicString& name, const String& value, ExceptionCode& ec)
  811. {
  812. if (m_state != OPENED || m_loader) {
  813. #if ENABLE(DASHBOARD_SUPPORT)
  814. if (usesDashboardBackwardCompatibilityMode())
  815. return;
  816. #endif
  817. ec = INVALID_STATE_ERR;
  818. return;
  819. }
  820. if (!isValidHTTPToken(name) || !isValidHTTPHeaderValue(value)) {
  821. ec = SYNTAX_ERR;
  822. return;
  823. }
  824. // A privileged script (e.g. a Dashboard widget) can set any headers.
  825. if (!securityOrigin()->canLoadLocalResources() && !isAllowedHTTPHeader(name)) {
  826. logConsoleError(scriptExecutionContext(), "Refused to set unsafe header \"" + name + "\"");
  827. return;
  828. }
  829. setRequestHeaderInternal(name, value);
  830. }
  831. void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const String& value)
  832. {
  833. HTTPHeaderMap::AddResult result = m_requestHeaders.add(name, value);
  834. if (!result.isNewEntry)
  835. result.iterator->value.append(", " + value);
  836. }
  837. String XMLHttpRequest::getRequestHeader(const AtomicString& name) const
  838. {
  839. return m_requestHeaders.get(name);
  840. }
  841. String XMLHttpRequest::getAllResponseHeaders(ExceptionCode& ec) const
  842. {
  843. if (m_state < HEADERS_RECEIVED) {
  844. ec = INVALID_STATE_ERR;
  845. return "";
  846. }
  847. StringBuilder stringBuilder;
  848. HTTPHeaderSet accessControlExposeHeaderSet;
  849. parseAccessControlExposeHeadersAllowList(m_response.httpHeaderField("Access-Control-Expose-Headers"), accessControlExposeHeaderSet);
  850. HTTPHeaderMap::const_iterator end = m_response.httpHeaderFields().end();
  851. for (HTTPHeaderMap::const_iterator it = m_response.httpHeaderFields().begin(); it!= end; ++it) {
  852. // Hide Set-Cookie header fields from the XMLHttpRequest client for these reasons:
  853. // 1) If the client did have access to the fields, then it could read HTTP-only
  854. // cookies; those cookies are supposed to be hidden from scripts.
  855. // 2) There's no known harm in hiding Set-Cookie header fields entirely; we don't
  856. // know any widely used technique that requires access to them.
  857. // 3) Firefox has implemented this policy.
  858. if (isSetCookieHeader(it->key) && !securityOrigin()->canLoadLocalResources())
  859. continue;
  860. if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(it->key) && !accessControlExposeHeaderSet.contains(it->key))
  861. continue;
  862. stringBuilder.append(it->key);
  863. stringBuilder.append(':');
  864. stringBuilder.append(' ');
  865. stringBuilder.append(it->value);
  866. stringBuilder.append('\r');
  867. stringBuilder.append('\n');
  868. }
  869. return stringBuilder.toString();
  870. }
  871. String XMLHttpRequest::getResponseHeader(const AtomicString& name, ExceptionCode& ec) const
  872. {
  873. if (m_state < HEADERS_RECEIVED) {
  874. ec = INVALID_STATE_ERR;
  875. return String();
  876. }
  877. // See comment in getAllResponseHeaders above.
  878. if (isSetCookieHeader(name) && !securityOrigin()->canLoadLocalResources()) {
  879. logConsoleError(scriptExecutionContext(), "Refused to get unsafe header \"" + name + "\"");
  880. return String();
  881. }
  882. HTTPHeaderSet accessControlExposeHeaderSet;
  883. parseAccessControlExposeHeadersAllowList(m_response.httpHeaderField("Access-Control-Expose-Headers"), accessControlExposeHeaderSet);
  884. if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(name) && !accessControlExposeHeaderSet.contains(name)) {
  885. logConsoleError(scriptExecutionContext(), "Refused to get unsafe header \"" + name + "\"");
  886. return String();
  887. }
  888. return m_response.httpHeaderField(name);
  889. }
  890. String XMLHttpRequest::responseMIMEType() const
  891. {
  892. String mimeType = extractMIMETypeFromMediaType(m_mimeTypeOverride);
  893. if (mimeType.isEmpty()) {
  894. if (m_response.isHTTP())
  895. mimeType = extractMIMETypeFromMediaType(m_response.httpHeaderField("Content-Type"));
  896. else
  897. mimeType = m_response.mimeType();
  898. }
  899. if (mimeType.isEmpty())
  900. mimeType = "text/xml";
  901. return mimeType;
  902. }
  903. bool XMLHttpRequest::responseIsXML() const
  904. {
  905. // FIXME: Remove the lower() call when DOMImplementation.isXMLMIMEType() is modified
  906. // to do case insensitive MIME type matching.
  907. return DOMImplementation::isXMLMIMEType(responseMIMEType().lower());
  908. }
  909. int XMLHttpRequest::status(ExceptionCode& ec) const
  910. {
  911. if (m_response.httpStatusCode())
  912. return m_response.httpStatusCode();
  913. if (m_state == OPENED) {
  914. // Firefox only raises an exception in this state; we match it.
  915. // Note the case of local file requests, where we have no HTTP response code! Firefox never raises an exception for those, but we match HTTP case for consistency.
  916. ec = INVALID_STATE_ERR;
  917. }
  918. return 0;
  919. }
  920. String XMLHttpRequest::statusText(ExceptionCode& ec) const
  921. {
  922. if (!m_response.httpStatusText().isNull())
  923. return m_response.httpStatusText();
  924. if (m_state == OPENED) {
  925. // See comments in status() above.
  926. ec = INVALID_STATE_ERR;
  927. }
  928. return String();
  929. }
  930. void XMLHttpRequest::didFail(const ResourceError& error)
  931. {
  932. // If we are already in an error state, for instance we called abort(), bail out early.
  933. if (m_error)
  934. return;
  935. if (error.isCancellation()) {
  936. m_exceptionCode = XMLHttpRequestException::ABORT_ERR;
  937. abortError();
  938. return;
  939. }
  940. #if ENABLE(XHR_TIMEOUT)
  941. if (error.isTimeout()) {
  942. didTimeout();
  943. return;
  944. }
  945. #endif
  946. // Network failures are already reported to Web Inspector by ResourceLoader.
  947. if (error.domain() == errorDomainWebKitInternal)
  948. logConsoleError(scriptExecutionContext(), "XMLHttpRequest cannot load " + error.failingURL() + ". " + error.localizedDescription());
  949. m_exceptionCode = XMLHttpRequestException::NETWORK_ERR;
  950. networkError();
  951. }
  952. void XMLHttpRequest::didFailRedirectCheck()
  953. {
  954. networkError();
  955. }
  956. void XMLHttpRequest::didFinishLoading(unsigned long identifier, double)
  957. {
  958. if (m_error)
  959. return;
  960. if (m_state < HEADERS_RECEIVED)
  961. changeState(HEADERS_RECEIVED);
  962. if (m_decoder)
  963. m_responseBuilder.append(m_decoder->flush());
  964. m_responseBuilder.shrinkToFit();
  965. InspectorInstrumentation::didFinishXHRLoading(scriptExecutionContext(), this, identifier, m_responseBuilder.toStringPreserveCapacity(), m_url, m_lastSendURL, m_lastSendLineNumber);
  966. bool hadLoader = m_loader;
  967. m_loader = 0;
  968. changeState(DONE);
  969. m_responseEncoding = String();
  970. m_decoder = 0;
  971. if (hadLoader)
  972. dropProtection();
  973. }
  974. void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
  975. {
  976. if (!m_upload)
  977. return;
  978. if (m_uploadEventsAllowed)
  979. m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, true, bytesSent, totalBytesToBeSent));
  980. if (bytesSent == totalBytesToBeSent && !m_uploadComplete) {
  981. m_uploadComplete = true;
  982. if (m_uploadEventsAllowed)
  983. m_upload->dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().loadEvent));
  984. }
  985. }
  986. void XMLHttpRequest::didReceiveResponse(unsigned long identifier, const ResourceResponse& response)
  987. {
  988. InspectorInstrumentation::didReceiveXHRResponse(scriptExecutionContext(), identifier);
  989. m_response = response;
  990. if (!m_mimeTypeOverride.isEmpty()) {
  991. m_response.setHTTPHeaderField("Content-Type", m_mimeTypeOverride);
  992. m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride);
  993. }
  994. if (m_responseEncoding.isEmpty())
  995. m_responseEncoding = response.textEncodingName();
  996. }
  997. void XMLHttpRequest::didReceiveData(const char* data, int len)
  998. {
  999. if (m_error)
  1000. return;
  1001. if (m_state < HEADERS_RECEIVED)
  1002. changeState(HEADERS_RECEIVED);
  1003. bool useDecoder = m_responseTypeCode == ResponseTypeDefault || m_responseTypeCode == ResponseTypeText || m_responseTypeCode == ResponseTypeDocument;
  1004. if (useDecoder && !m_decoder) {
  1005. if (!m_responseEncoding.isEmpty())
  1006. m_decoder = TextResourceDecoder::create("text/plain", m_responseEncoding);
  1007. // allow TextResourceDecoder to look inside the m_response if it's XML or HTML
  1008. else if (responseIsXML()) {
  1009. m_decoder = TextResourceDecoder::create("application/xml");
  1010. // Don't stop on encoding errors, unlike it is done for other kinds of XML resources. This matches the behavior of previous WebKit versions, Firefox and Opera.
  1011. m_decoder->useLenientXMLDecoding();
  1012. } else if (equalIgnoringCase(responseMIMEType(), "text/html"))
  1013. m_decoder = TextResourceDecoder::create("text/html", "UTF-8");
  1014. else
  1015. m_decoder = TextResourceDecoder::create("text/plain", "UTF-8");
  1016. }
  1017. if (!len)
  1018. return;
  1019. if (len == -1)
  1020. len = strlen(data);
  1021. if (useDecoder)
  1022. m_responseBuilder.append(m_decoder->decode(data, len));
  1023. else if (m_responseTypeCode == ResponseTypeArrayBuffer || m_responseTypeCode == ResponseTypeBlob) {
  1024. // Buffer binary data.
  1025. if (!m_binaryResponseBuilder)
  1026. m_binaryResponseBuilder = SharedBuffer::create();
  1027. m_binaryResponseBuilder->append(data, len);
  1028. }
  1029. if (!m_error) {
  1030. long long expectedLength = m_response.expectedContentLength();
  1031. m_receivedLength += len;
  1032. if (m_async) {
  1033. bool lengthComputable = expectedLength > 0 && m_receivedLength <= expectedLength;
  1034. unsigned long long total = lengthComputable ? expectedLength : 0;
  1035. m_progressEventThrottle.dispatchProgressEvent(lengthComputable, m_receivedLength, total);
  1036. }
  1037. if (m_state != LOADING)
  1038. changeState(LOADING);
  1039. else
  1040. // Firefox calls readyStateChanged every time it receives data, 4449442
  1041. callReadyStateChangeListener();
  1042. }
  1043. }
  1044. #if ENABLE(XHR_TIMEOUT)
  1045. void XMLHttpRequest::didTimeout()
  1046. {
  1047. // internalAbort() calls dropProtection(), which may release the last reference.
  1048. RefPtr<XMLHttpRequest> protect(this);
  1049. internalAbort();
  1050. clearResponse();
  1051. clearRequest();
  1052. m_error = true;
  1053. m_exceptionCode = XMLHttpRequestException::TIMEOUT_ERR;
  1054. if (!m_async) {
  1055. m_state = DONE;
  1056. m_exceptionCode = TIMEOUT_ERR;
  1057. return;
  1058. }
  1059. changeState(DONE);
  1060. if (!m_uploadComplete) {
  1061. m_uploadComplete = true;
  1062. if (m_upload && m_uploadEventsAllowed)
  1063. m_upload->dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().timeoutEvent));
  1064. }
  1065. m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(eventNames().timeoutEvent));
  1066. }
  1067. #endif
  1068. bool XMLHttpRequest::canSuspend() const
  1069. {
  1070. return !m_loader;
  1071. }
  1072. void XMLHttpRequest::suspend(ReasonForSuspension)
  1073. {
  1074. m_progressEventThrottle.suspend();
  1075. }
  1076. void XMLHttpRequest::resume()
  1077. {
  1078. m_progressEventThrottle.resume();
  1079. }
  1080. void XMLHttpRequest::stop()
  1081. {
  1082. internalAbort();
  1083. }
  1084. void XMLHttpRequest::contextDestroyed()
  1085. {
  1086. ASSERT(!m_loader);
  1087. ActiveDOMObject::contextDestroyed();
  1088. }
  1089. const AtomicString& XMLHttpRequest::interfaceName() const
  1090. {
  1091. return eventNames().interfaceForXMLHttpRequest;
  1092. }
  1093. ScriptExecutionContext* XMLHttpRequest::scriptExecutionContext() const
  1094. {
  1095. return ActiveDOMObject::scriptExecutionContext();
  1096. }
  1097. EventTargetData* XMLHttpRequest::eventTargetData()
  1098. {
  1099. return &m_eventTargetData;
  1100. }
  1101. EventTargetData* XMLHttpRequest::ensureEventTargetData()
  1102. {
  1103. return &m_eventTargetData;
  1104. }
  1105. } // namespace WebCore