OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "FetchManager.h" | 6 #include "FetchManager.h" |
7 | 7 |
8 #include "bindings/core/v8/ExceptionState.h" | 8 #include "bindings/core/v8/ExceptionState.h" |
9 #include "bindings/core/v8/ScriptPromiseResolver.h" | 9 #include "bindings/core/v8/ScriptPromiseResolver.h" |
10 #include "bindings/core/v8/ScriptState.h" | 10 #include "bindings/core/v8/ScriptState.h" |
11 #include "bindings/core/v8/V8ThrowException.h" | 11 #include "bindings/core/v8/V8ThrowException.h" |
12 #include "core/dom/ExceptionCode.h" | 12 #include "core/dom/ExceptionCode.h" |
13 #include "core/fileapi/Blob.h" | 13 #include "core/fileapi/Blob.h" |
14 #include "core/loader/ThreadableLoader.h" | 14 #include "core/loader/ThreadableLoader.h" |
15 #include "core/loader/ThreadableLoaderClient.h" | 15 #include "core/loader/ThreadableLoaderClient.h" |
16 #include "core/xml/XMLHttpRequest.h" | 16 #include "core/xml/XMLHttpRequest.h" |
| 17 #include "modules/serviceworkers/FetchRequestData.h" |
17 #include "modules/serviceworkers/Response.h" | 18 #include "modules/serviceworkers/Response.h" |
18 #include "modules/serviceworkers/ResponseInit.h" | 19 #include "modules/serviceworkers/ResponseInit.h" |
19 #include "platform/network/ResourceRequest.h" | 20 #include "platform/network/ResourceRequest.h" |
| 21 #include "platform/weborigin/SecurityOrigin.h" |
| 22 #include "public/platform/WebURLRequest.h" |
20 #include "wtf/HashSet.h" | 23 #include "wtf/HashSet.h" |
21 | 24 |
22 namespace WebCore { | 25 namespace WebCore { |
23 | 26 |
24 class FetchManager::Loader : public ThreadableLoaderClient { | 27 class FetchManager::Loader : public ThreadableLoaderClient { |
25 public: | 28 public: |
26 Loader(ExecutionContext*, FetchManager*, PassRefPtr<ScriptPromiseResolver>,
PassOwnPtr<ResourceRequest>); | 29 Loader(ExecutionContext*, FetchManager*, PassRefPtr<ScriptPromiseResolver>,
PassRefPtr<FetchRequestData>); |
27 ~Loader(); | 30 ~Loader(); |
28 virtual void didReceiveResponse(unsigned long, const ResourceResponse&); | 31 virtual void didReceiveResponse(unsigned long, const ResourceResponse&); |
29 virtual void didFinishLoading(unsigned long, double); | 32 virtual void didFinishLoading(unsigned long, double); |
30 virtual void didFail(const ResourceError&); | 33 virtual void didFail(const ResourceError&); |
31 virtual void didFailAccessControlCheck(const ResourceError&); | 34 virtual void didFailAccessControlCheck(const ResourceError&); |
32 virtual void didFailRedirectCheck(); | 35 virtual void didFailRedirectCheck(); |
33 virtual void didDownloadData(int); | 36 virtual void didDownloadData(int); |
34 | 37 |
35 void start(); | 38 void start(); |
36 void cleanup(); | 39 void cleanup(); |
37 | 40 |
38 private: | 41 private: |
| 42 void performBasicFetch(); |
| 43 void performNetworkError(); |
| 44 void performeHTTPFetch(); |
39 void failed(); | 45 void failed(); |
40 void notifyFinished(); | 46 void notifyFinished(); |
41 | 47 |
42 ExecutionContext* m_executionContext; | 48 ExecutionContext* m_executionContext; |
43 FetchManager* m_fetchManager; | 49 FetchManager* m_fetchManager; |
44 RefPtr<ScriptPromiseResolver> m_resolver; | 50 RefPtr<ScriptPromiseResolver> m_resolver; |
45 OwnPtr<ResourceRequest> m_request; | 51 RefPtr<FetchRequestData> m_request; |
46 RefPtr<ThreadableLoader> m_loader; | 52 RefPtr<ThreadableLoader> m_loader; |
47 ResourceResponse m_response; | 53 ResourceResponse m_response; |
48 long long m_downloadedBlobLength; | 54 long long m_downloadedBlobLength; |
| 55 bool m_corsFlag; |
| 56 bool m_corsPreflightFlag; |
49 bool m_failed; | 57 bool m_failed; |
50 }; | 58 }; |
51 | 59 |
52 FetchManager::Loader::Loader(ExecutionContext* executionContext, FetchManager* f
etchManager, PassRefPtr<ScriptPromiseResolver> resolver, PassOwnPtr<ResourceRequ
est> request) | 60 FetchManager::Loader::Loader(ExecutionContext* executionContext, FetchManager* f
etchManager, PassRefPtr<ScriptPromiseResolver> resolver, PassRefPtr<FetchRequest
Data> request) |
53 : m_executionContext(executionContext) | 61 : m_executionContext(executionContext) |
54 , m_fetchManager(fetchManager) | 62 , m_fetchManager(fetchManager) |
55 , m_resolver(resolver) | 63 , m_resolver(resolver) |
56 , m_request(request) | 64 , m_request(request->createCopy()) |
57 , m_downloadedBlobLength(0) | 65 , m_downloadedBlobLength(0) |
| 66 , m_corsFlag(false) |
| 67 , m_corsPreflightFlag(false) |
58 , m_failed(false) | 68 , m_failed(false) |
59 { | 69 { |
60 } | 70 } |
61 | 71 |
62 FetchManager::Loader::~Loader() | 72 FetchManager::Loader::~Loader() |
63 { | 73 { |
64 if (m_loader) | 74 if (m_loader) |
65 m_loader->cancel(); | 75 m_loader->cancel(); |
66 } | 76 } |
67 | 77 |
68 void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceRespo
nse& response) | 78 void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceRespo
nse& response) |
69 { | 79 { |
70 m_response = response; | 80 m_response = response; |
| 81 return; |
71 } | 82 } |
72 | 83 |
73 void FetchManager::Loader::didFinishLoading(unsigned long, double) | 84 void FetchManager::Loader::didFinishLoading(unsigned long, double) |
74 { | 85 { |
75 OwnPtr<BlobData> blobData = BlobData::create(); | 86 OwnPtr<BlobData> blobData = BlobData::create(); |
76 String filePath = m_response.downloadedFilePath(); | 87 String filePath = m_response.downloadedFilePath(); |
77 if (!filePath.isEmpty() && m_downloadedBlobLength) { | 88 if (!filePath.isEmpty() && m_downloadedBlobLength) { |
78 blobData->appendFile(filePath); | 89 blobData->appendFile(filePath); |
79 blobData->setContentType(m_response.mimeType()); | 90 blobData->setContentType(m_response.mimeType()); |
80 } | 91 } |
81 ResponseInit responseInit; | 92 RefPtr<FetchResponseData> response(FetchResponseData::create()); |
82 // FIXME: We may have to filter the status when we support CORS. | 93 response->setStatus(m_response.httpStatusCode()); |
83 // http://fetch.spec.whatwg.org/#concept-filtered-response-opaque | 94 response->setStatusMessage(m_response.httpStatusText()); |
84 responseInit.status = m_response.httpStatusCode(); | 95 HTTPHeaderMap::const_iterator end = m_response.httpHeaderFields().end(); |
85 responseInit.statusText = m_response.httpStatusText(); | 96 for (HTTPHeaderMap::const_iterator it = m_response.httpHeaderFields().begin(
); it != end; ++it) { |
86 // FIXME: fill options. | 97 response->headerList()->append(it->key, it->value); |
87 RefPtrWillBeRawPtr<Blob> blob = Blob::create(BlobDataHandle::create(blobData
.release(), m_downloadedBlobLength)); | 98 } |
88 // FIXME: Handle response status correctly. | 99 response->setBlobDataHandle(BlobDataHandle::create(blobData.release(), m_dow
nloadedBlobLength)); |
89 NonThrowableExceptionState exceptionState; | 100 response->setURL(m_request->url()); |
90 m_resolver->resolve(Response::create(blob.get(), responseInit, exceptionStat
e)); | 101 |
| 102 switch (m_request->tainting()) { |
| 103 case FetchRequestData::BasicTainting: |
| 104 response = response->createBasicFilteredResponse(); |
| 105 break; |
| 106 case FetchRequestData::CORSTainting: |
| 107 response = response->createCORSFilteredResponse(); |
| 108 break; |
| 109 case FetchRequestData::OpaqueTainting: |
| 110 response = response->createOpaqueFilteredResponse(); |
| 111 break; |
| 112 } |
| 113 m_resolver->resolve(Response::create(response.release())); |
91 notifyFinished(); | 114 notifyFinished(); |
92 } | 115 } |
93 | 116 |
94 void FetchManager::Loader::didFail(const ResourceError& error) | 117 void FetchManager::Loader::didFail(const ResourceError& error) |
95 { | 118 { |
96 failed(); | 119 failed(); |
97 } | 120 } |
98 | 121 |
99 void FetchManager::Loader::didFailAccessControlCheck(const ResourceError& error) | 122 void FetchManager::Loader::didFailAccessControlCheck(const ResourceError& error) |
100 { | 123 { |
101 failed(); | 124 failed(); |
102 } | 125 } |
103 | 126 |
104 void FetchManager::Loader::didFailRedirectCheck() | 127 void FetchManager::Loader::didFailRedirectCheck() |
105 { | 128 { |
106 failed(); | 129 failed(); |
107 } | 130 } |
108 | 131 |
109 void FetchManager::Loader::didDownloadData(int dataLength) | 132 void FetchManager::Loader::didDownloadData(int dataLength) |
110 { | 133 { |
111 m_downloadedBlobLength += dataLength; | 134 m_downloadedBlobLength += dataLength; |
112 } | 135 } |
113 | 136 |
114 void FetchManager::Loader::start() | 137 void FetchManager::Loader::start() |
115 { | 138 { |
116 m_request->setDownloadToFile(true); | 139 |
117 ThreadableLoaderOptions options; | 140 // "1. If |request|'s url contains a Known HSTS Host, modify it perthe |
118 // FIXME: Fill options. | 141 // requirements of the 'URI [sic] Loading and Port Mapping' chapter of HTTP |
119 ResourceLoaderOptions resourceLoaderOptions; | 142 // Strict Transport Security." |
120 resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData; | 143 // FIXME: Implement this. |
121 // FIXME: Fill resourceLoaderOptions. | 144 |
122 m_loader = ThreadableLoader::create(*m_executionContext, this, *m_request, o
ptions, resourceLoaderOptions); | 145 // "2. If |request|'s referrer is not none, set |request|'s referrer to the |
| 146 // result of invoking determine |request|'s referrer." |
| 147 // We set the referrer using workerGlobalScope's URL in |
| 148 // WorkerThreadableLoader. |
| 149 |
| 150 // "3. If |request|'s synchronous flag is unset and fetch is not invoked |
| 151 // recursively, run the remaining steps asynchronously." |
| 152 // FIXME: We don't support synchronous flag. |
| 153 |
| 154 // "4. Let response be the value corresponding to the first matching |
| 155 // statement:" |
| 156 |
| 157 // "- should fetching |request| be blocked as mixed content returns blocked |
| 158 // - should fetching |request| be blocked as content security returns |
| 159 // blocked |
| 160 // A network error." |
| 161 // We do mixed content checking and CSP checking in ResourceFetcher. |
| 162 |
| 163 // "- |request|'s url's origin is |request|'s origin and the |CORS flag| is
unset |
| 164 // "- |request|'s url's scheme is 'data' and |request|'s same-origin data UR
L |
| 165 // flag is set |
| 166 // "- |request|'s url's scheme is 'about'" |
| 167 if ((SecurityOrigin::create(m_request->url())->isSameSchemeHostPort(m_reques
t->origin().get()) && !m_corsFlag) |
| 168 || (m_request->url().protocol() == "data" && m_request->sameOriginDataUR
LFlag()) |
| 169 || (m_request->url().protocol() == "about")) { |
| 170 // "The result of performing a basic fetch using request." |
| 171 performBasicFetch(); |
| 172 return; |
| 173 } |
| 174 |
| 175 // "- |request|'s mode is |same-origin|" |
| 176 if (m_request->mode() == FetchRequestData::SameOriginMode) { |
| 177 // "A network error." |
| 178 performNetworkError(); |
| 179 return; |
| 180 } |
| 181 |
| 182 // "- |request|'s mode is |no CORS|" |
| 183 if (m_request->mode() == FetchRequestData::NoCORSMode) { |
| 184 // "Set |request|'s response tainting to |opaque|." |
| 185 m_request->setResponseTainting(FetchRequestData::OpaqueTainting); |
| 186 // "The result of performing a basic fetch using |request|." |
| 187 performBasicFetch(); |
| 188 return; |
| 189 } |
| 190 |
| 191 // "- |request|'s url's scheme is not one of 'http' and 'https'" |
| 192 if (m_request->url().protocol() != "http" && m_request->url().protocol() !=
"https") { |
| 193 // "A network error." |
| 194 performNetworkError(); |
| 195 return; |
| 196 } |
| 197 |
| 198 // "- |request|'s mode is |CORS-with-forced-preflight|. |
| 199 if (m_request->mode() == FetchRequestData::CORSWithForcedPreflight) { |
| 200 // "Set |request|'s response tainting to |CORS|." |
| 201 m_request->setResponseTainting(FetchRequestData::CORSTainting); |
| 202 // "The result of performing an HTTP fetch using |request| with the |
| 203 // |CORS flag| and |CORS preflight flag| set." |
| 204 m_corsFlag = true; |
| 205 m_corsPreflightFlag = true; |
| 206 performeHTTPFetch(); |
| 207 return; |
| 208 } |
| 209 |
| 210 // "- |request|'s unsafe request flag is set and either |request|'s method |
| 211 // is not a simple method or a header in |request|'s header list is not a |
| 212 // simple header" |
| 213 if (m_request->unsafeRequestFlag() |
| 214 && (!isSimpleMethod(m_request->method()) |
| 215 || m_request->headerList()->containsNonSimpleHeader())) { |
| 216 // "Set |request|'s response tainting to |CORS|." |
| 217 m_request->setResponseTainting(FetchRequestData::CORSTainting); |
| 218 // "The result of performing an HTTP fetch using |request| with the |
| 219 // |CORS flag| and |CORS preflight flag| set." |
| 220 m_corsFlag = true; |
| 221 m_corsPreflightFlag = true; |
| 222 performeHTTPFetch(); |
| 223 return; |
| 224 } |
| 225 |
| 226 // "- Otherwise |
| 227 // Set |request|'s response tainting to |CORS|." |
| 228 m_request->setResponseTainting(FetchRequestData::CORSTainting); |
| 229 // "The result of performing an HTTP fetch using |request| with the |
| 230 // |CORS flag| set." |
| 231 m_corsFlag = true; |
| 232 m_corsPreflightFlag = false; |
| 233 performeHTTPFetch(); |
123 } | 234 } |
124 | 235 |
125 void FetchManager::Loader::cleanup() | 236 void FetchManager::Loader::cleanup() |
126 { | 237 { |
127 // Prevent notification | 238 // Prevent notification |
128 m_fetchManager = 0; | 239 m_fetchManager = 0; |
129 | 240 |
130 if (m_loader) { | 241 if (m_loader) { |
131 m_loader->cancel(); | 242 m_loader->cancel(); |
132 m_loader.clear(); | 243 m_loader.clear(); |
133 } | 244 } |
134 } | 245 } |
135 | 246 |
| 247 void FetchManager::Loader::performBasicFetch() |
| 248 { |
| 249 // "To perform a basic fetch using |request|, switch on |request|'s url's |
| 250 // scheme, and run the associated steps:" |
| 251 String protocol(m_request->url().protocol()); |
| 252 if (protocol == "about") { |
| 253 // FIXME: implement this. |
| 254 performNetworkError(); |
| 255 } else if (protocol == "blob") { |
| 256 // FIXME: implement this. |
| 257 performNetworkError(); |
| 258 } else if (protocol == "data") { |
| 259 // FIXME: implement this. |
| 260 performNetworkError(); |
| 261 } else if (protocol == "file" || protocol == "ftp") { |
| 262 // "For now, unfortunate as it is, file and ftp URLs are left as an |
| 263 // exercise for the reader. When in doubt, return a network error." |
| 264 // FIXME: implement this. |
| 265 performNetworkError(); |
| 266 } else if (protocol == "http" || protocol == "https") { |
| 267 // "Return the result of performing an HTTP fetch using |request|." |
| 268 m_corsFlag = false; |
| 269 m_corsPreflightFlag = false; |
| 270 performeHTTPFetch(); |
| 271 } else { |
| 272 // "Return a network error." |
| 273 performNetworkError(); |
| 274 } |
| 275 } |
| 276 |
| 277 void FetchManager::Loader::performNetworkError() |
| 278 { |
| 279 failed(); |
| 280 } |
| 281 |
| 282 void FetchManager::Loader::performeHTTPFetch() |
| 283 { |
| 284 // "1. Let |HTTPRequest| be a copy of |request|, except that |HTTPRequest|'s |
| 285 // body is a tee of |request|'s body." |
| 286 // We use ResourceRequest class for HTTPRequest. |
| 287 // FIXME: Support body. |
| 288 ResourceRequest request(m_request->url()); |
| 289 request.setRequestContext(blink::WebURLRequest::RequestContextFetch); |
| 290 request.setDownloadToFile(true); |
| 291 request.setHTTPMethod(m_request->method()); |
| 292 const Vector<OwnPtr<FetchHeaderList::Header> >& list = m_request->headerList
()->list(); |
| 293 for (size_t i = 0; i < list.size(); ++i) { |
| 294 request.addHTTPHeaderField(AtomicString(list[i]->first), AtomicString(li
st[i]->second)); |
| 295 } |
| 296 |
| 297 // "2. Append `Referer`/empty byte sequence, if |HTTPRequest|'s |referrer| |
| 298 // is none, and `Referer`/|HTTPRequest|'s referrer, serialized and utf-8 |
| 299 // encoded, otherwise, to HTTPRequest's header list. |
| 300 // We set the referrer using workerGlobalScope's URL in |
| 301 // WorkerThreadableLoader. |
| 302 |
| 303 // "3. Append `Host`, ..." |
| 304 // FIXME: Implement this when the spec is fixed. |
| 305 |
| 306 // "4.If |HTTPRequest|'s force Origin header flag is set, append `Origin`/ |
| 307 // |HTTPRequest|'s origin, serialized and utf-8 encoded, to |HTTPRequest|'s |
| 308 // header list." |
| 309 // FIXME: We don't support Origin header yet. |
| 310 |
| 311 // "5. Let |credentials flag| be set if either |HTTPRequest|'s credentials |
| 312 // mode is |include|, or |HTTPRequest|'s credentials mode is |same-origin| |
| 313 // and the |CORS flag| is unset, and unset otherwise. |
| 314 ResourceLoaderOptions resourceLoaderOptions; |
| 315 resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData; |
| 316 if (m_request->credentials() == FetchRequestData::IncludeCredentials |
| 317 || (m_request->credentials() == FetchRequestData::SameOriginCredentials
&& !m_corsFlag)) { |
| 318 resourceLoaderOptions.allowCredentials = AllowStoredCredentials; |
| 319 } |
| 320 if (m_request->credentials() == FetchRequestData::IncludeCredentials) |
| 321 resourceLoaderOptions.credentialsRequested = ClientRequestedCredentials; |
| 322 |
| 323 ThreadableLoaderOptions threadableLoaderOptions; |
| 324 if (m_corsPreflightFlag) |
| 325 threadableLoaderOptions.preflightPolicy = ForcePreflight; |
| 326 if (m_corsFlag) |
| 327 threadableLoaderOptions.crossOriginRequestPolicy = UseAccessControl; |
| 328 else |
| 329 threadableLoaderOptions.crossOriginRequestPolicy = AllowCrossOriginReque
sts; |
| 330 |
| 331 |
| 332 m_loader = ThreadableLoader::create(*m_executionContext, this, request, thre
adableLoaderOptions, resourceLoaderOptions); |
| 333 } |
| 334 |
136 void FetchManager::Loader::failed() | 335 void FetchManager::Loader::failed() |
137 { | 336 { |
138 if (m_failed) | 337 if (m_failed) |
139 return; | 338 return; |
140 m_failed = true; | 339 m_failed = true; |
141 ScriptState* state = m_resolver->scriptState(); | 340 ScriptState* state = m_resolver->scriptState(); |
142 ScriptState::Scope scope(state); | 341 ScriptState::Scope scope(state); |
143 m_resolver->reject(V8ThrowException::createTypeError("Failed to fetch", stat
e->isolate())); | 342 m_resolver->reject(V8ThrowException::createTypeError("Failed to fetch", stat
e->isolate())); |
144 notifyFinished(); | 343 notifyFinished(); |
145 } | 344 } |
146 | 345 |
147 void FetchManager::Loader::notifyFinished() | 346 void FetchManager::Loader::notifyFinished() |
148 { | 347 { |
149 if (m_fetchManager) | 348 if (m_fetchManager) |
150 m_fetchManager->onLoaderFinished(this); | 349 m_fetchManager->onLoaderFinished(this); |
151 } | 350 } |
152 | 351 |
153 FetchManager::FetchManager(ExecutionContext* executionContext) | 352 FetchManager::FetchManager(ExecutionContext* executionContext) |
154 : m_executionContext(executionContext) | 353 : m_executionContext(executionContext) |
155 { | 354 { |
156 } | 355 } |
157 | 356 |
158 FetchManager::~FetchManager() | 357 FetchManager::~FetchManager() |
159 { | 358 { |
160 for (HashSet<OwnPtr<Loader> >::iterator it = m_loaders.begin(); it != m_load
ers.end(); ++it) { | 359 for (HashSet<OwnPtr<Loader> >::iterator it = m_loaders.begin(); it != m_load
ers.end(); ++it) { |
161 (*it)->cleanup(); | 360 (*it)->cleanup(); |
162 } | 361 } |
163 } | 362 } |
164 | 363 |
165 ScriptPromise FetchManager::fetch(ScriptState* scriptState, PassOwnPtr<ResourceR
equest> request) | 364 ScriptPromise FetchManager::fetch(ScriptState* scriptState, PassRefPtr<FetchRequ
estData> request) |
166 { | 365 { |
167 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scrip
tState); | 366 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scrip
tState); |
168 ScriptPromise promise = resolver->promise(); | 367 ScriptPromise promise = resolver->promise(); |
169 | 368 |
170 OwnPtr<Loader> loader(adoptPtr(new Loader(m_executionContext, this, resolver
.release(), request))); | 369 OwnPtr<Loader> ownLoader(adoptPtr(new Loader(m_executionContext, this, resol
ver.release(), request))); |
171 (*m_loaders.add(loader.release()).storedValue)->start(); | 370 Loader* loader = m_loaders.add(ownLoader.release()).storedValue->get(); |
| 371 loader->start(); |
172 return promise; | 372 return promise; |
173 } | 373 } |
174 | 374 |
175 void FetchManager::onLoaderFinished(Loader* loader) | 375 void FetchManager::onLoaderFinished(Loader* loader) |
176 { | 376 { |
177 m_loaders.remove(loader); | 377 m_loaders.remove(loader); |
178 } | 378 } |
179 | 379 |
180 bool FetchManager::isSimpleMethod(const String& method) | 380 bool FetchManager::isSimpleMethod(const String& method) |
181 { | 381 { |
182 // "A simple method is a method that is `GET`, `HEAD`, or `POST`." | 382 // "A simple method is a method that is `GET`, `HEAD`, or `POST`." |
183 return isOnAccessControlSimpleRequestMethodWhitelist(method); | 383 return isOnAccessControlSimpleRequestMethodWhitelist(method); |
184 } | 384 } |
185 | 385 |
186 bool FetchManager::isForbiddenMethod(const String& method) | 386 bool FetchManager::isForbiddenMethod(const String& method) |
187 { | 387 { |
188 // "A forbidden method is a method that is a byte case-insensitive match for
one of `CONNECT`, `TRACE`, and `TRACK`." | 388 // "A forbidden method is a method that is a byte case-insensitive match for |
| 389 // one of `CONNECT`, `TRACE`, and `TRACK`." |
189 return !XMLHttpRequest::isAllowedHTTPMethod(method); | 390 return !XMLHttpRequest::isAllowedHTTPMethod(method); |
190 } | 391 } |
191 | 392 |
192 bool FetchManager::isUsefulMethod(const String& method) | 393 bool FetchManager::isUsefulMethod(const String& method) |
193 { | 394 { |
194 // "A useful method is a method that is not a forbidden method." | 395 // "A useful method is a method that is not a forbidden method." |
195 // "A forbidden method is a method that is a byte case-insensitive match for
one of `CONNECT`, `TRACE`, and `TRACK`." | 396 // "A forbidden method is a method that is a byte case-insensitive match for |
| 397 // one of `CONNECT`, `TRACE`, and `TRACK`." |
196 return XMLHttpRequest::isAllowedHTTPMethod(method); | 398 return XMLHttpRequest::isAllowedHTTPMethod(method); |
197 } | 399 } |
198 | 400 |
199 } // namespace WebCore | 401 } // namespace WebCore |
OLD | NEW |