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

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: rebase Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 #include "wtf/ArrayBufferView.h" 59 #include "wtf/ArrayBufferView.h"
60 #include "wtf/Assertions.h" 60 #include "wtf/Assertions.h"
61 #include "wtf/RefCountedLeakCounter.h" 61 #include "wtf/RefCountedLeakCounter.h"
62 #include "wtf/StdLibExtras.h" 62 #include "wtf/StdLibExtras.h"
63 #include "wtf/text/CString.h" 63 #include "wtf/text/CString.h"
64 64
65 namespace WebCore { 65 namespace WebCore {
66 66
67 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, xmlHttpRequestCounter, ("XM LHttpRequest")); 67 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, xmlHttpRequestCounter, ("XM LHttpRequest"));
68 68
69 struct XMLHttpRequestStaticData {
70 WTF_MAKE_NONCOPYABLE(XMLHttpRequestStaticData); WTF_MAKE_FAST_ALLOCATED;
71 public:
72 XMLHttpRequestStaticData();
73 String m_proxyHeaderPrefix;
74 String m_secHeaderPrefix;
75 HashSet<String, CaseFoldingHash> m_forbiddenRequestHeaders;
76 };
77
78 XMLHttpRequestStaticData::XMLHttpRequestStaticData()
79 : m_proxyHeaderPrefix("proxy-")
80 , m_secHeaderPrefix("sec-")
81 {
82 m_forbiddenRequestHeaders.add("accept-charset");
83 m_forbiddenRequestHeaders.add("accept-encoding");
84 m_forbiddenRequestHeaders.add("access-control-request-headers");
85 m_forbiddenRequestHeaders.add("access-control-request-method");
86 m_forbiddenRequestHeaders.add("connection");
87 m_forbiddenRequestHeaders.add("content-length");
88 m_forbiddenRequestHeaders.add("cookie");
89 m_forbiddenRequestHeaders.add("cookie2");
90 m_forbiddenRequestHeaders.add("date");
91 m_forbiddenRequestHeaders.add("dnt");
92 m_forbiddenRequestHeaders.add("expect");
93 m_forbiddenRequestHeaders.add("host");
94 m_forbiddenRequestHeaders.add("keep-alive");
95 m_forbiddenRequestHeaders.add("origin");
96 m_forbiddenRequestHeaders.add("referer");
97 m_forbiddenRequestHeaders.add("te");
98 m_forbiddenRequestHeaders.add("trailer");
99 m_forbiddenRequestHeaders.add("transfer-encoding");
100 m_forbiddenRequestHeaders.add("upgrade");
101 m_forbiddenRequestHeaders.add("user-agent");
102 m_forbiddenRequestHeaders.add("via");
103 }
104
105 static bool isSetCookieHeader(const AtomicString& name) 69 static bool isSetCookieHeader(const AtomicString& name)
106 { 70 {
107 return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set -cookie2"); 71 return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set -cookie2");
108 } 72 }
109 73
110 static void replaceCharsetInMediaType(String& mediaType, const String& charsetVa lue) 74 static void replaceCharsetInMediaType(String& mediaType, const String& charsetVa lue)
111 { 75 {
112 unsigned pos = 0, len = 0; 76 unsigned pos = 0, len = 0;
113 77
114 findCharsetInMediaType(mediaType, pos, len); 78 findCharsetInMediaType(mediaType, pos, len);
115 79
116 if (!len) { 80 if (!len) {
117 // When no charset found, do nothing. 81 // When no charset found, do nothing.
118 return; 82 return;
119 } 83 }
120 84
121 // Found at least one existing charset, replace all occurrences with new cha rset. 85 // Found at least one existing charset, replace all occurrences with new cha rset.
122 while (len) { 86 while (len) {
123 mediaType.replace(pos, len, charsetValue); 87 mediaType.replace(pos, len, charsetValue);
124 unsigned start = pos + charsetValue.length(); 88 unsigned start = pos + charsetValue.length();
125 findCharsetInMediaType(mediaType, pos, len, start); 89 findCharsetInMediaType(mediaType, pos, len, start);
126 } 90 }
127 } 91 }
128 92
129 static const XMLHttpRequestStaticData* staticData = 0;
130
131 static const XMLHttpRequestStaticData* createXMLHttpRequestStaticData()
132 {
133 staticData = new XMLHttpRequestStaticData;
134 return staticData;
135 }
136
137 static const XMLHttpRequestStaticData* initializeXMLHttpRequestStaticData()
138 {
139 // Uses dummy to avoid warnings about an unused variable.
140 AtomicallyInitializedStatic(const XMLHttpRequestStaticData*, dummy = createX MLHttpRequestStaticData());
141 return dummy;
142 }
143
144 static void logConsoleError(ExecutionContext* context, const String& message) 93 static void logConsoleError(ExecutionContext* context, const String& message)
145 { 94 {
146 if (!context) 95 if (!context)
147 return; 96 return;
148 // FIXME: It's not good to report the bad usage without indicating what sour ce line it came from. 97 // FIXME: It's not good to report the bad usage without indicating what sour ce line it came from.
149 // We should pass additional parameters so we can tell the console where the mistake occurred. 98 // We should pass additional parameters so we can tell the console where the mistake occurred.
150 context->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message); 99 context->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message);
151 } 100 }
152 101
153 PassRefPtrWillBeRawPtr<XMLHttpRequest> XMLHttpRequest::create(ExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin) 102 PassRefPtrWillBeRawPtr<XMLHttpRequest> XMLHttpRequest::create(ExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin)
(...skipping 16 matching lines...) Expand all
170 , m_responseTypeCode(ResponseTypeDefault) 119 , m_responseTypeCode(ResponseTypeDefault)
171 , m_securityOrigin(securityOrigin) 120 , m_securityOrigin(securityOrigin)
172 , m_async(true) 121 , m_async(true)
173 , m_includeCredentials(false) 122 , m_includeCredentials(false)
174 , m_createdDocument(false) 123 , m_createdDocument(false)
175 , m_error(false) 124 , m_error(false)
176 , m_uploadEventsAllowed(true) 125 , m_uploadEventsAllowed(true)
177 , m_uploadComplete(false) 126 , m_uploadComplete(false)
178 , m_sameOriginRequest(true) 127 , m_sameOriginRequest(true)
179 { 128 {
180 initializeXMLHttpRequestStaticData();
181 #ifndef NDEBUG 129 #ifndef NDEBUG
182 xmlHttpRequestCounter.increment(); 130 xmlHttpRequestCounter.increment();
183 #endif 131 #endif
184 ScriptWrappable::init(this); 132 ScriptWrappable::init(this);
185 } 133 }
186 134
187 XMLHttpRequest::~XMLHttpRequest() 135 XMLHttpRequest::~XMLHttpRequest()
188 { 136 {
189 #ifndef NDEBUG 137 #ifndef NDEBUG
190 xmlHttpRequestCounter.decrement(); 138 xmlHttpRequestCounter.decrement();
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 } 428 }
481 429
482 // FIXME: According to XMLHttpRequest Level 2 we should throw InvalidAccessE rror exception here. 430 // FIXME: According to XMLHttpRequest Level 2 we should throw InvalidAccessE rror exception here.
483 // However for time being only print warning message to warn web developers. 431 // However for time being only print warning message to warn web developers.
484 if (!m_async) 432 if (!m_async)
485 UseCounter::countDeprecation(executionContext(), UseCounter::SyncXHRWith Credentials); 433 UseCounter::countDeprecation(executionContext(), UseCounter::SyncXHRWith Credentials);
486 434
487 m_includeCredentials = value; 435 m_includeCredentials = value;
488 } 436 }
489 437
490 bool XMLHttpRequest::isAllowedHTTPMethod(const String& method)
491 {
492 return !equalIgnoringCase(method, "TRACE")
493 && !equalIgnoringCase(method, "TRACK")
494 && !equalIgnoringCase(method, "CONNECT");
495 }
496
497 AtomicString XMLHttpRequest::uppercaseKnownHTTPMethod(const AtomicString& method ) 438 AtomicString XMLHttpRequest::uppercaseKnownHTTPMethod(const AtomicString& method )
498 { 439 {
499 // Valid methods per step-5 of http://xhr.spec.whatwg.org/#the-open()-method . 440 // Valid methods per step-5 of http://xhr.spec.whatwg.org/#the-open()-method .
500 const char* const methods[] = { 441 const char* const methods[] = {
501 "DELETE", 442 "DELETE",
502 "GET", 443 "GET",
503 "HEAD", 444 "HEAD",
504 "OPTIONS", 445 "OPTIONS",
505 "POST", 446 "POST",
506 "PUT" }; 447 "PUT" };
507 448
508 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(methods); ++i) { 449 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(methods); ++i) {
509 if (equalIgnoringCase(method, methods[i])) { 450 if (equalIgnoringCase(method, methods[i])) {
510 // Don't bother allocating a new string if it's already all uppercas e. 451 // Don't bother allocating a new string if it's already all uppercas e.
511 if (method == methods[i]) 452 if (method == methods[i])
512 return method; 453 return method;
513 return methods[i]; 454 return methods[i];
514 } 455 }
515 } 456 }
516 return method; 457 return method;
517 } 458 }
518 459
519 bool XMLHttpRequest::isAllowedHTTPHeader(const String& name)
520 {
521 initializeXMLHttpRequestStaticData();
522 return !staticData->m_forbiddenRequestHeaders.contains(name) && !name.starts With(staticData->m_proxyHeaderPrefix, false)
523 && !name.startsWith(staticData->m_secHeaderPrefix, false);
524 }
525
526 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, Exception State& exceptionState) 460 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, Exception State& exceptionState)
527 { 461 {
528 open(method, url, true, exceptionState); 462 open(method, url, true, exceptionState);
529 } 463 }
530 464
531 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, bool asyn c, ExceptionState& exceptionState) 465 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, bool asyn c, ExceptionState& exceptionState)
532 { 466 {
533 WTF_LOG(Network, "XMLHttpRequest %p open('%s', '%s', %d)", this, method.utf8 ().data(), url.elidedString().utf8().data(), async); 467 WTF_LOG(Network, "XMLHttpRequest %p open('%s', '%s', %d)", this, method.utf8 ().data(), url.elidedString().utf8().data(), async);
534 468
535 if (!internalAbort()) 469 if (!internalAbort())
536 return; 470 return;
537 471
538 State previousState = m_state; 472 State previousState = m_state;
539 m_state = UNSENT; 473 m_state = UNSENT;
540 m_error = false; 474 m_error = false;
541 m_uploadComplete = false; 475 m_uploadComplete = false;
542 476
543 // clear stuff from possible previous load 477 // clear stuff from possible previous load
544 clearResponse(); 478 clearResponse();
545 clearRequest(); 479 clearRequest();
546 480
547 ASSERT(m_state == UNSENT); 481 ASSERT(m_state == UNSENT);
548 482
549 if (!isValidHTTPToken(method)) { 483 if (!isValidHTTPToken(method)) {
550 exceptionState.throwDOMException(SyntaxError, "'" + method + "' is not a valid HTTP method."); 484 exceptionState.throwDOMException(SyntaxError, "'" + method + "' is not a valid HTTP method.");
551 return; 485 return;
552 } 486 }
553 487
554 if (!isAllowedHTTPMethod(method)) { 488 if (CrossOriginAccessControl::isForbiddenMethod(method)) {
555 exceptionState.throwSecurityError("'" + method + "' HTTP method is unsup ported."); 489 exceptionState.throwSecurityError("'" + method + "' HTTP method is unsup ported.");
556 return; 490 return;
557 } 491 }
558 492
559 if (!ContentSecurityPolicy::shouldBypassMainWorld(executionContext()) && !ex ecutionContext()->contentSecurityPolicy()->allowConnectToSource(url)) { 493 if (!ContentSecurityPolicy::shouldBypassMainWorld(executionContext()) && !ex ecutionContext()->contentSecurityPolicy()->allowConnectToSource(url)) {
560 // We can safely expose the URL to JavaScript, as these checks happen sy nchronously before redirection. JavaScript receives no new information. 494 // We can safely expose the URL to JavaScript, as these checks happen sy nchronously before redirection. JavaScript receives no new information.
561 exceptionState.throwSecurityError("Refused to connect to '" + url.elided String() + "' because it violates the document's Content Security Policy."); 495 exceptionState.throwSecurityError("Refused to connect to '" + url.elided String() + "' because it violates the document's Content Security Policy.");
562 return; 496 return;
563 } 497 }
564 498
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
808 if (httpBody && m_upload) { 742 if (httpBody && m_upload) {
809 uploadEvents = m_upload->hasEventListeners(); 743 uploadEvents = m_upload->hasEventListeners();
810 m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(EventTyp eNames::loadstart)); 744 m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(EventTyp eNames::loadstart));
811 } 745 }
812 } 746 }
813 747
814 m_sameOriginRequest = securityOrigin()->canRequest(m_url); 748 m_sameOriginRequest = securityOrigin()->canRequest(m_url);
815 749
816 // We also remember whether upload events should be allowed for this request in case the upload listeners are 750 // We also remember whether upload events should be allowed for this request in case the upload listeners are
817 // added after the request is started. 751 // added after the request is started.
818 m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCros sOriginAccessRequest(m_method, m_requestHeaders); 752 m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !CrossOriginA ccessControl::isSimpleRequest(m_method, m_requestHeaders);
819 753
820 ASSERT(executionContext()); 754 ASSERT(executionContext());
821 ExecutionContext& executionContext = *this->executionContext(); 755 ExecutionContext& executionContext = *this->executionContext();
822 756
823 ResourceRequest request(m_url); 757 ResourceRequest request(m_url);
824 request.setHTTPMethod(m_method); 758 request.setHTTPMethod(m_method);
825 request.setRequestContext(blink::WebURLRequest::RequestContextXMLHttpRequest ); 759 request.setRequestContext(blink::WebURLRequest::RequestContextXMLHttpRequest );
826 760
827 InspectorInstrumentation::willLoadXHR(&executionContext, this, this, m_metho d, m_url, m_async, httpBody ? httpBody->deepCopy() : nullptr, m_requestHeaders, m_includeCredentials); 761 InspectorInstrumentation::willLoadXHR(&executionContext, this, this, m_metho d, m_url, m_async, httpBody ? httpBody->deepCopy() : nullptr, m_requestHeaders, m_includeCredentials);
828 762
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
1074 exceptionState.throwDOMException(SyntaxError, "'" + name + "' is not a v alid HTTP header field name."); 1008 exceptionState.throwDOMException(SyntaxError, "'" + name + "' is not a v alid HTTP header field name.");
1075 return; 1009 return;
1076 } 1010 }
1077 1011
1078 if (!isValidHTTPHeaderValue(value)) { 1012 if (!isValidHTTPHeaderValue(value)) {
1079 exceptionState.throwDOMException(SyntaxError, "'" + value + "' is not a valid HTTP header field value."); 1013 exceptionState.throwDOMException(SyntaxError, "'" + value + "' is not a valid HTTP header field value.");
1080 return; 1014 return;
1081 } 1015 }
1082 1016
1083 // No script (privileged or not) can set unsafe headers. 1017 // No script (privileged or not) can set unsafe headers.
1084 if (!isAllowedHTTPHeader(name)) { 1018 if (CrossOriginAccessControl::isForbiddenHeaderName(name)) {
1085 logConsoleError(executionContext(), "Refused to set unsafe header \"" + name + "\""); 1019 logConsoleError(executionContext(), "Refused to set unsafe header \"" + name + "\"");
1086 return; 1020 return;
1087 } 1021 }
1088 1022
1089 setRequestHeaderInternal(name, value); 1023 setRequestHeaderInternal(name, value);
1090 } 1024 }
1091 1025
1092 void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const At omicString& value) 1026 void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const At omicString& value)
1093 { 1027 {
1094 HTTPHeaderMap::AddResult result = m_requestHeaders.add(name, value); 1028 HTTPHeaderMap::AddResult result = m_requestHeaders.add(name, value);
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
1424 { 1358 {
1425 visitor->trace(m_responseBlob); 1359 visitor->trace(m_responseBlob);
1426 visitor->trace(m_responseStream); 1360 visitor->trace(m_responseStream);
1427 visitor->trace(m_responseDocument); 1361 visitor->trace(m_responseDocument);
1428 visitor->trace(m_progressEventThrottle); 1362 visitor->trace(m_progressEventThrottle);
1429 visitor->trace(m_upload); 1363 visitor->trace(m_upload);
1430 XMLHttpRequestEventTarget::trace(visitor); 1364 XMLHttpRequestEventTarget::trace(visitor);
1431 } 1365 }
1432 1366
1433 } // namespace WebCore 1367 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698