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

Side by Side Diff: Source/core/xml/XMLHttpRequest.cpp

Issue 379113002: Move fetch-related predicates to core/fetch. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/xml/XMLHttpRequest.h ('k') | Source/modules/serviceworkers/FetchHeaderList.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 13 matching lines...) Expand all
24 #include "core/xml/XMLHttpRequest.h" 24 #include "core/xml/XMLHttpRequest.h"
25 25
26 #include "bindings/core/v8/ExceptionState.h" 26 #include "bindings/core/v8/ExceptionState.h"
27 #include "core/FetchInitiatorTypeNames.h" 27 #include "core/FetchInitiatorTypeNames.h"
28 #include "core/dom/ContextFeatures.h" 28 #include "core/dom/ContextFeatures.h"
29 #include "core/dom/DOMImplementation.h" 29 #include "core/dom/DOMImplementation.h"
30 #include "core/dom/ExceptionCode.h" 30 #include "core/dom/ExceptionCode.h"
31 #include "core/dom/XMLDocument.h" 31 #include "core/dom/XMLDocument.h"
32 #include "core/editing/markup.h" 32 #include "core/editing/markup.h"
33 #include "core/events/Event.h" 33 #include "core/events/Event.h"
34 #include "core/fetch/CrossOriginAccessControl.h" 34 #include "core/fetch/FetchUtils.h"
35 #include "core/fileapi/Blob.h" 35 #include "core/fileapi/Blob.h"
36 #include "core/fileapi/File.h" 36 #include "core/fileapi/File.h"
37 #include "core/frame/Settings.h" 37 #include "core/frame/Settings.h"
38 #include "core/frame/UseCounter.h" 38 #include "core/frame/UseCounter.h"
39 #include "core/frame/csp/ContentSecurityPolicy.h" 39 #include "core/frame/csp/ContentSecurityPolicy.h"
40 #include "core/html/DOMFormData.h" 40 #include "core/html/DOMFormData.h"
41 #include "core/html/HTMLDocument.h" 41 #include "core/html/HTMLDocument.h"
42 #include "core/html/parser/TextResourceDecoder.h" 42 #include "core/html/parser/TextResourceDecoder.h"
43 #include "core/inspector/InspectorInstrumentation.h" 43 #include "core/inspector/InspectorInstrumentation.h"
44 #include "core/inspector/InspectorTraceEvents.h" 44 #include "core/inspector/InspectorTraceEvents.h"
(...skipping 25 matching lines...) Expand all
70 // As dispatching readystatechange when readystatechange is NOT changed is not 70 // As dispatching readystatechange when readystatechange is NOT changed is not
71 // specified, 50ms is not specified, too. 71 // specified, 50ms is not specified, too.
72 // We choose this value because progress event is dispatched every 50ms, but 72 // We choose this value because progress event is dispatched every 50ms, but
73 // actually this value doesn't have to equal to the interval. 73 // actually this value doesn't have to equal to the interval.
74 // Note: When readystate is actually changed readystatechange event must be 74 // Note: When readystate is actually changed readystatechange event must be
75 // dispatched no matter how recently dispatched the event was. 75 // dispatched no matter how recently dispatched the event was.
76 const double readyStateChangeFireInterval = 0.05; 76 const double readyStateChangeFireInterval = 0.05;
77 77
78 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, xmlHttpRequestCounter, ("XM LHttpRequest")); 78 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, xmlHttpRequestCounter, ("XM LHttpRequest"));
79 79
80 struct XMLHttpRequestStaticData {
81 WTF_MAKE_NONCOPYABLE(XMLHttpRequestStaticData); WTF_MAKE_FAST_ALLOCATED;
82 public:
83 XMLHttpRequestStaticData();
84 String m_proxyHeaderPrefix;
85 String m_secHeaderPrefix;
86 HashSet<String, CaseFoldingHash> m_forbiddenRequestHeaders;
87 };
88
89 XMLHttpRequestStaticData::XMLHttpRequestStaticData()
90 : m_proxyHeaderPrefix("proxy-")
91 , m_secHeaderPrefix("sec-")
92 {
93 m_forbiddenRequestHeaders.add("accept-charset");
94 m_forbiddenRequestHeaders.add("accept-encoding");
95 m_forbiddenRequestHeaders.add("access-control-request-headers");
96 m_forbiddenRequestHeaders.add("access-control-request-method");
97 m_forbiddenRequestHeaders.add("connection");
98 m_forbiddenRequestHeaders.add("content-length");
99 m_forbiddenRequestHeaders.add("cookie");
100 m_forbiddenRequestHeaders.add("cookie2");
101 m_forbiddenRequestHeaders.add("date");
102 m_forbiddenRequestHeaders.add("dnt");
103 m_forbiddenRequestHeaders.add("expect");
104 m_forbiddenRequestHeaders.add("host");
105 m_forbiddenRequestHeaders.add("keep-alive");
106 m_forbiddenRequestHeaders.add("origin");
107 m_forbiddenRequestHeaders.add("referer");
108 m_forbiddenRequestHeaders.add("te");
109 m_forbiddenRequestHeaders.add("trailer");
110 m_forbiddenRequestHeaders.add("transfer-encoding");
111 m_forbiddenRequestHeaders.add("upgrade");
112 m_forbiddenRequestHeaders.add("user-agent");
113 m_forbiddenRequestHeaders.add("via");
114 }
115
116 static bool isSetCookieHeader(const AtomicString& name) 80 static bool isSetCookieHeader(const AtomicString& name)
117 { 81 {
118 return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set -cookie2"); 82 return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set -cookie2");
119 } 83 }
120 84
121 static void replaceCharsetInMediaType(String& mediaType, const String& charsetVa lue) 85 static void replaceCharsetInMediaType(String& mediaType, const String& charsetVa lue)
122 { 86 {
123 unsigned pos = 0, len = 0; 87 unsigned pos = 0, len = 0;
124 88
125 findCharsetInMediaType(mediaType, pos, len); 89 findCharsetInMediaType(mediaType, pos, len);
126 90
127 if (!len) { 91 if (!len) {
128 // When no charset found, do nothing. 92 // When no charset found, do nothing.
129 return; 93 return;
130 } 94 }
131 95
132 // Found at least one existing charset, replace all occurrences with new cha rset. 96 // Found at least one existing charset, replace all occurrences with new cha rset.
133 while (len) { 97 while (len) {
134 mediaType.replace(pos, len, charsetValue); 98 mediaType.replace(pos, len, charsetValue);
135 unsigned start = pos + charsetValue.length(); 99 unsigned start = pos + charsetValue.length();
136 findCharsetInMediaType(mediaType, pos, len, start); 100 findCharsetInMediaType(mediaType, pos, len, start);
137 } 101 }
138 } 102 }
139 103
140 static const XMLHttpRequestStaticData* staticData = 0;
141
142 static const XMLHttpRequestStaticData* createXMLHttpRequestStaticData()
143 {
144 staticData = new XMLHttpRequestStaticData;
145 return staticData;
146 }
147
148 static const XMLHttpRequestStaticData* initializeXMLHttpRequestStaticData()
149 {
150 // Uses dummy to avoid warnings about an unused variable.
151 AtomicallyInitializedStatic(const XMLHttpRequestStaticData*, dummy = createX MLHttpRequestStaticData());
152 return dummy;
153 }
154
155 static void logConsoleError(ExecutionContext* context, const String& message) 104 static void logConsoleError(ExecutionContext* context, const String& message)
156 { 105 {
157 if (!context) 106 if (!context)
158 return; 107 return;
159 // FIXME: It's not good to report the bad usage without indicating what sour ce line it came from. 108 // FIXME: It's not good to report the bad usage without indicating what sour ce line it came from.
160 // We should pass additional parameters so we can tell the console where the mistake occurred. 109 // We should pass additional parameters so we can tell the console where the mistake occurred.
161 context->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message); 110 context->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message);
162 } 111 }
163 112
164 PassRefPtrWillBeRawPtr<XMLHttpRequest> XMLHttpRequest::create(ExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin) 113 PassRefPtrWillBeRawPtr<XMLHttpRequest> XMLHttpRequest::create(ExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin)
(...skipping 17 matching lines...) Expand all
182 , m_securityOrigin(securityOrigin) 131 , m_securityOrigin(securityOrigin)
183 , m_previousReadyStateChangeFireTime(0) 132 , m_previousReadyStateChangeFireTime(0)
184 , m_async(true) 133 , m_async(true)
185 , m_includeCredentials(false) 134 , m_includeCredentials(false)
186 , m_createdDocument(false) 135 , m_createdDocument(false)
187 , m_error(false) 136 , m_error(false)
188 , m_uploadEventsAllowed(true) 137 , m_uploadEventsAllowed(true)
189 , m_uploadComplete(false) 138 , m_uploadComplete(false)
190 , m_sameOriginRequest(true) 139 , m_sameOriginRequest(true)
191 { 140 {
192 initializeXMLHttpRequestStaticData();
193 #ifndef NDEBUG 141 #ifndef NDEBUG
194 xmlHttpRequestCounter.increment(); 142 xmlHttpRequestCounter.increment();
195 #endif 143 #endif
196 ScriptWrappable::init(this); 144 ScriptWrappable::init(this);
197 } 145 }
198 146
199 XMLHttpRequest::~XMLHttpRequest() 147 XMLHttpRequest::~XMLHttpRequest()
200 { 148 {
201 #ifndef NDEBUG 149 #ifndef NDEBUG
202 xmlHttpRequestCounter.decrement(); 150 xmlHttpRequestCounter.decrement();
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 } 443 }
496 444
497 // FIXME: According to XMLHttpRequest Level 2 we should throw InvalidAccessE rror exception here. 445 // FIXME: According to XMLHttpRequest Level 2 we should throw InvalidAccessE rror exception here.
498 // However for time being only print warning message to warn web developers. 446 // However for time being only print warning message to warn web developers.
499 if (!m_async) 447 if (!m_async)
500 UseCounter::countDeprecation(executionContext(), UseCounter::SyncXHRWith Credentials); 448 UseCounter::countDeprecation(executionContext(), UseCounter::SyncXHRWith Credentials);
501 449
502 m_includeCredentials = value; 450 m_includeCredentials = value;
503 } 451 }
504 452
505 bool XMLHttpRequest::isAllowedHTTPMethod(const String& method)
506 {
507 return !equalIgnoringCase(method, "TRACE")
508 && !equalIgnoringCase(method, "TRACK")
509 && !equalIgnoringCase(method, "CONNECT");
510 }
511
512 AtomicString XMLHttpRequest::uppercaseKnownHTTPMethod(const AtomicString& method ) 453 AtomicString XMLHttpRequest::uppercaseKnownHTTPMethod(const AtomicString& method )
513 { 454 {
514 // Valid methods per step-5 of http://xhr.spec.whatwg.org/#the-open()-method . 455 // Valid methods per step-5 of http://xhr.spec.whatwg.org/#the-open()-method .
515 const char* const methods[] = { 456 const char* const methods[] = {
516 "DELETE", 457 "DELETE",
517 "GET", 458 "GET",
518 "HEAD", 459 "HEAD",
519 "OPTIONS", 460 "OPTIONS",
520 "POST", 461 "POST",
521 "PUT" }; 462 "PUT" };
522 463
523 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(methods); ++i) { 464 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(methods); ++i) {
524 if (equalIgnoringCase(method, methods[i])) { 465 if (equalIgnoringCase(method, methods[i])) {
525 // Don't bother allocating a new string if it's already all uppercas e. 466 // Don't bother allocating a new string if it's already all uppercas e.
526 if (method == methods[i]) 467 if (method == methods[i])
527 return method; 468 return method;
528 return methods[i]; 469 return methods[i];
529 } 470 }
530 } 471 }
531 return method; 472 return method;
532 } 473 }
533 474
534 bool XMLHttpRequest::isAllowedHTTPHeader(const String& name)
535 {
536 initializeXMLHttpRequestStaticData();
537 return !staticData->m_forbiddenRequestHeaders.contains(name) && !name.starts With(staticData->m_proxyHeaderPrefix, false)
538 && !name.startsWith(staticData->m_secHeaderPrefix, false);
539 }
540
541 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, Exception State& exceptionState) 475 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, Exception State& exceptionState)
542 { 476 {
543 open(method, url, true, exceptionState); 477 open(method, url, true, exceptionState);
544 } 478 }
545 479
546 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, bool asyn c, ExceptionState& exceptionState) 480 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, bool asyn c, ExceptionState& exceptionState)
547 { 481 {
548 WTF_LOG(Network, "XMLHttpRequest %p open('%s', '%s', %d)", this, method.utf8 ().data(), url.elidedString().utf8().data(), async); 482 WTF_LOG(Network, "XMLHttpRequest %p open('%s', '%s', %d)", this, method.utf8 ().data(), url.elidedString().utf8().data(), async);
549 483
550 if (!internalAbort()) 484 if (!internalAbort())
551 return; 485 return;
552 486
553 State previousState = m_state; 487 State previousState = m_state;
554 m_state = UNSENT; 488 m_state = UNSENT;
555 m_error = false; 489 m_error = false;
556 m_uploadComplete = false; 490 m_uploadComplete = false;
557 491
558 // clear stuff from possible previous load 492 // clear stuff from possible previous load
559 clearResponse(); 493 clearResponse();
560 clearRequest(); 494 clearRequest();
561 495
562 ASSERT(m_state == UNSENT); 496 ASSERT(m_state == UNSENT);
563 497
564 if (!isValidHTTPToken(method)) { 498 if (!isValidHTTPToken(method)) {
565 exceptionState.throwDOMException(SyntaxError, "'" + method + "' is not a valid HTTP method."); 499 exceptionState.throwDOMException(SyntaxError, "'" + method + "' is not a valid HTTP method.");
566 return; 500 return;
567 } 501 }
568 502
569 if (!isAllowedHTTPMethod(method)) { 503 if (FetchUtils::isForbiddenMethod(method)) {
570 exceptionState.throwSecurityError("'" + method + "' HTTP method is unsup ported."); 504 exceptionState.throwSecurityError("'" + method + "' HTTP method is unsup ported.");
571 return; 505 return;
572 } 506 }
573 507
574 if (!ContentSecurityPolicy::shouldBypassMainWorld(executionContext()) && !ex ecutionContext()->contentSecurityPolicy()->allowConnectToSource(url)) { 508 if (!ContentSecurityPolicy::shouldBypassMainWorld(executionContext()) && !ex ecutionContext()->contentSecurityPolicy()->allowConnectToSource(url)) {
575 // We can safely expose the URL to JavaScript, as these checks happen sy nchronously before redirection. JavaScript receives no new information. 509 // We can safely expose the URL to JavaScript, as these checks happen sy nchronously before redirection. JavaScript receives no new information.
576 exceptionState.throwSecurityError("Refused to connect to '" + url.elided String() + "' because it violates the document's Content Security Policy."); 510 exceptionState.throwSecurityError("Refused to connect to '" + url.elided String() + "' because it violates the document's Content Security Policy.");
577 return; 511 return;
578 } 512 }
579 513
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 if (httpBody && m_upload) { 757 if (httpBody && m_upload) {
824 uploadEvents = m_upload->hasEventListeners(); 758 uploadEvents = m_upload->hasEventListeners();
825 m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(EventTyp eNames::loadstart)); 759 m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(EventTyp eNames::loadstart));
826 } 760 }
827 } 761 }
828 762
829 m_sameOriginRequest = securityOrigin()->canRequest(m_url); 763 m_sameOriginRequest = securityOrigin()->canRequest(m_url);
830 764
831 // We also remember whether upload events should be allowed for this request in case the upload listeners are 765 // We also remember whether upload events should be allowed for this request in case the upload listeners are
832 // added after the request is started. 766 // added after the request is started.
833 m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCros sOriginAccessRequest(m_method, m_requestHeaders); 767 m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !FetchUtils:: isSimpleRequest(m_method, m_requestHeaders);
834 768
835 ASSERT(executionContext()); 769 ASSERT(executionContext());
836 ExecutionContext& executionContext = *this->executionContext(); 770 ExecutionContext& executionContext = *this->executionContext();
837 771
838 ResourceRequest request(m_url); 772 ResourceRequest request(m_url);
839 request.setHTTPMethod(m_method); 773 request.setHTTPMethod(m_method);
840 request.setRequestContext(blink::WebURLRequest::RequestContextXMLHttpRequest ); 774 request.setRequestContext(blink::WebURLRequest::RequestContextXMLHttpRequest );
841 775
842 InspectorInstrumentation::willLoadXHR(&executionContext, this, this, m_metho d, m_url, m_async, httpBody ? httpBody->deepCopy() : nullptr, m_requestHeaders, m_includeCredentials); 776 InspectorInstrumentation::willLoadXHR(&executionContext, this, this, m_metho d, m_url, m_async, httpBody ? httpBody->deepCopy() : nullptr, m_requestHeaders, m_includeCredentials);
843 777
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
1089 exceptionState.throwDOMException(SyntaxError, "'" + name + "' is not a v alid HTTP header field name."); 1023 exceptionState.throwDOMException(SyntaxError, "'" + name + "' is not a v alid HTTP header field name.");
1090 return; 1024 return;
1091 } 1025 }
1092 1026
1093 if (!isValidHTTPHeaderValue(value)) { 1027 if (!isValidHTTPHeaderValue(value)) {
1094 exceptionState.throwDOMException(SyntaxError, "'" + value + "' is not a valid HTTP header field value."); 1028 exceptionState.throwDOMException(SyntaxError, "'" + value + "' is not a valid HTTP header field value.");
1095 return; 1029 return;
1096 } 1030 }
1097 1031
1098 // No script (privileged or not) can set unsafe headers. 1032 // No script (privileged or not) can set unsafe headers.
1099 if (!isAllowedHTTPHeader(name)) { 1033 if (FetchUtils::isForbiddenHeaderName(name)) {
1100 logConsoleError(executionContext(), "Refused to set unsafe header \"" + name + "\""); 1034 logConsoleError(executionContext(), "Refused to set unsafe header \"" + name + "\"");
1101 return; 1035 return;
1102 } 1036 }
1103 1037
1104 setRequestHeaderInternal(name, value); 1038 setRequestHeaderInternal(name, value);
1105 } 1039 }
1106 1040
1107 void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const At omicString& value) 1041 void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const At omicString& value)
1108 { 1042 {
1109 HTTPHeaderMap::AddResult result = m_requestHeaders.add(name, value); 1043 HTTPHeaderMap::AddResult result = m_requestHeaders.add(name, value);
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
1439 { 1373 {
1440 visitor->trace(m_responseBlob); 1374 visitor->trace(m_responseBlob);
1441 visitor->trace(m_responseStream); 1375 visitor->trace(m_responseStream);
1442 visitor->trace(m_responseDocument); 1376 visitor->trace(m_responseDocument);
1443 visitor->trace(m_progressEventThrottle); 1377 visitor->trace(m_progressEventThrottle);
1444 visitor->trace(m_upload); 1378 visitor->trace(m_upload);
1445 XMLHttpRequestEventTarget::trace(visitor); 1379 XMLHttpRequestEventTarget::trace(visitor);
1446 } 1380 }
1447 1381
1448 } // namespace blink 1382 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/xml/XMLHttpRequest.h ('k') | Source/modules/serviceworkers/FetchHeaderList.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698