Chromium Code Reviews| 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 blink { | 25 namespace blink { |
| 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 performHTTPFetch(); | |
| 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; |
| 71 } | 81 } |
| 72 | 82 |
| 73 void FetchManager::Loader::didFinishLoading(unsigned long, double) | 83 void FetchManager::Loader::didFinishLoading(unsigned long, double) |
| 74 { | 84 { |
| 75 OwnPtr<BlobData> blobData = BlobData::create(); | 85 OwnPtr<BlobData> blobData = BlobData::create(); |
| 76 String filePath = m_response.downloadedFilePath(); | 86 String filePath = m_response.downloadedFilePath(); |
| 77 if (!filePath.isEmpty() && m_downloadedBlobLength) { | 87 if (!filePath.isEmpty() && m_downloadedBlobLength) { |
| 78 blobData->appendFile(filePath); | 88 blobData->appendFile(filePath); |
| 79 blobData->setContentType(m_response.mimeType()); | 89 blobData->setContentType(m_response.mimeType()); |
| 80 } | 90 } |
| 81 ResponseInit responseInit; | 91 RefPtr<FetchResponseData> response(FetchResponseData::create()); |
| 82 // FIXME: We may have to filter the status when we support CORS. | 92 response->setStatus(m_response.httpStatusCode()); |
| 83 // http://fetch.spec.whatwg.org/#concept-filtered-response-opaque | 93 response->setStatusMessage(m_response.httpStatusText()); |
| 84 responseInit.status = m_response.httpStatusCode(); | 94 HTTPHeaderMap::const_iterator end = m_response.httpHeaderFields().end(); |
| 85 responseInit.statusText = m_response.httpStatusText(); | 95 for (HTTPHeaderMap::const_iterator it = m_response.httpHeaderFields().begin( ); it != end; ++it) { |
| 86 // FIXME: fill options. | 96 response->headerList()->append(it->key, it->value); |
| 87 RefPtrWillBeRawPtr<Blob> blob = Blob::create(BlobDataHandle::create(blobData .release(), m_downloadedBlobLength)); | 97 } |
| 88 // FIXME: Handle response status correctly. | 98 response->setBlobDataHandle(BlobDataHandle::create(blobData.release(), m_dow nloadedBlobLength)); |
| 89 NonThrowableExceptionState exceptionState; | 99 response->setURL(m_request->url()); |
| 90 m_resolver->resolve(Response::create(blob.get(), responseInit, exceptionStat e)); | 100 |
| 101 switch (m_request->tainting()) { | |
| 102 case FetchRequestData::BasicTainting: | |
| 103 response = response->createBasicFilteredResponse(); | |
| 104 break; | |
| 105 case FetchRequestData::CORSTainting: | |
| 106 response = response->createCORSFilteredResponse(); | |
| 107 break; | |
| 108 case FetchRequestData::OpaqueTainting: | |
| 109 response = response->createOpaqueFilteredResponse(); | |
| 110 break; | |
| 111 } | |
| 112 m_resolver->resolve(Response::create(response.release())); | |
| 91 notifyFinished(); | 113 notifyFinished(); |
| 92 } | 114 } |
| 93 | 115 |
| 94 void FetchManager::Loader::didFail(const ResourceError& error) | 116 void FetchManager::Loader::didFail(const ResourceError& error) |
| 95 { | 117 { |
| 96 failed(); | 118 failed(); |
| 97 } | 119 } |
| 98 | 120 |
| 99 void FetchManager::Loader::didFailAccessControlCheck(const ResourceError& error) | 121 void FetchManager::Loader::didFailAccessControlCheck(const ResourceError& error) |
| 100 { | 122 { |
| 101 failed(); | 123 failed(); |
| 102 } | 124 } |
| 103 | 125 |
| 104 void FetchManager::Loader::didFailRedirectCheck() | 126 void FetchManager::Loader::didFailRedirectCheck() |
| 105 { | 127 { |
| 106 failed(); | 128 failed(); |
| 107 } | 129 } |
| 108 | 130 |
| 109 void FetchManager::Loader::didDownloadData(int dataLength) | 131 void FetchManager::Loader::didDownloadData(int dataLength) |
| 110 { | 132 { |
| 111 m_downloadedBlobLength += dataLength; | 133 m_downloadedBlobLength += dataLength; |
| 112 } | 134 } |
| 113 | 135 |
| 114 void FetchManager::Loader::start() | 136 void FetchManager::Loader::start() |
| 115 { | 137 { |
| 116 m_request->setDownloadToFile(true); | 138 |
| 117 ThreadableLoaderOptions options; | 139 // "1. If |request|'s url contains a Known HSTS Host, modify it perthe |
|
falken
2014/07/25 05:41:29
s/perthe/per the/
horo
2014/07/25 06:00:56
Done.
| |
| 118 // FIXME: Fill options. | 140 // requirements of the 'URI [sic] Loading and Port Mapping' chapter of HTTP |
| 119 ResourceLoaderOptions resourceLoaderOptions; | 141 // Strict Transport Security." |
| 120 resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData; | 142 // FIXME: Implement this. |
| 121 // FIXME: Fill resourceLoaderOptions. | 143 |
| 122 m_loader = ThreadableLoader::create(*m_executionContext, this, *m_request, o ptions, resourceLoaderOptions); | 144 // "2. If |request|'s referrer is not none, set |request|'s referrer to the |
| 145 // result of invoking determine |request|'s referrer." | |
| 146 // We set the referrer using workerGlobalScope's URL in | |
| 147 // WorkerThreadableLoader. | |
| 148 | |
| 149 // "3. If |request|'s synchronous flag is unset and fetch is not invoked | |
| 150 // recursively, run the remaining steps asynchronously." | |
| 151 // We don't support synchronous flag. | |
| 152 | |
| 153 // "4. Let response be the value corresponding to the first matching | |
| 154 // statement:" | |
| 155 | |
| 156 // "- should fetching |request| be blocked as mixed content returns blocked | |
| 157 // - should fetching |request| be blocked as content security returns | |
| 158 // blocked | |
| 159 // A network error." | |
| 160 // We do mixed content checking and CSP checking in ResourceFetcher. | |
| 161 | |
| 162 // "- |request|'s url's origin is |request|'s origin and the |CORS flag| is | |
| 163 // unset" | |
| 164 // "- |request|'s url's scheme is 'data' and |request|'s same-origin data | |
| 165 // URL 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().protocolIsData() && m_request->sameOriginDataURLFla g()) | |
| 169 || (m_request->url().protocolIsAbout())) { | |
| 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().protocolIsInHTTPFamily()) { | |
| 193 // "A network error." | |
| 194 performNetworkError(); | |
| 195 return; | |
| 196 } | |
| 197 | |
| 198 // "- |request|'s mode is |CORS-with-forced-preflight|. | |
| 199 // "- |request|'s unsafe request flag is set and either |request|'s method | |
| 200 // is not a simple method or a header in |request|'s header list is not a | |
| 201 // simple header" | |
| 202 if (m_request->mode() == FetchRequestData::CORSWithForcedPreflight | |
| 203 || (m_request->unsafeRequestFlag() | |
| 204 && (!isSimpleMethod(m_request->method()) | |
| 205 || m_request->headerList()->containsNonSimpleHeader()))) { | |
| 206 // "Set |request|'s response tainting to |CORS|." | |
| 207 m_request->setResponseTainting(FetchRequestData::CORSTainting); | |
| 208 // "The result of performing an HTTP fetch using |request| with the | |
| 209 // |CORS flag| and |CORS preflight flag| set." | |
| 210 m_corsFlag = true; | |
| 211 m_corsPreflightFlag = true; | |
| 212 performHTTPFetch(); | |
| 213 return; | |
| 214 } | |
| 215 | |
| 216 // "- Otherwise | |
| 217 // Set |request|'s response tainting to |CORS|." | |
| 218 m_request->setResponseTainting(FetchRequestData::CORSTainting); | |
| 219 // "The result of performing an HTTP fetch using |request| with the | |
| 220 // |CORS flag| set." | |
| 221 m_corsFlag = true; | |
| 222 m_corsPreflightFlag = false; | |
| 223 performHTTPFetch(); | |
| 123 } | 224 } |
| 124 | 225 |
| 125 void FetchManager::Loader::cleanup() | 226 void FetchManager::Loader::cleanup() |
| 126 { | 227 { |
| 127 // Prevent notification | 228 // Prevent notification |
| 128 m_fetchManager = 0; | 229 m_fetchManager = 0; |
| 129 | 230 |
| 130 if (m_loader) { | 231 if (m_loader) { |
| 131 m_loader->cancel(); | 232 m_loader->cancel(); |
| 132 m_loader.clear(); | 233 m_loader.clear(); |
| 133 } | 234 } |
| 134 } | 235 } |
| 135 | 236 |
| 237 void FetchManager::Loader::performBasicFetch() | |
| 238 { | |
| 239 // "To perform a basic fetch using |request|, switch on |request|'s url's | |
| 240 // scheme, and run the associated steps:" | |
| 241 if (m_request->url().protocolIsInHTTPFamily()) { | |
| 242 // "Return the result of performing an HTTP fetch using |request|." | |
| 243 m_corsFlag = false; | |
| 244 m_corsPreflightFlag = false; | |
| 245 performHTTPFetch(); | |
| 246 } else { | |
| 247 // FIXME: implement other protocols. | |
| 248 performNetworkError(); | |
| 249 } | |
| 250 } | |
| 251 | |
| 252 void FetchManager::Loader::performNetworkError() | |
| 253 { | |
| 254 failed(); | |
| 255 } | |
| 256 | |
| 257 void FetchManager::Loader::performHTTPFetch() | |
| 258 { | |
| 259 // CORS preflight fetch procedure is implemented inside DocumentThreadableLo ader. | |
| 260 | |
| 261 // "1. Let |HTTPRequest| be a copy of |request|, except that |HTTPRequest|'s | |
| 262 // body is a tee of |request|'s body." | |
| 263 // We use ResourceRequest class for HTTPRequest. | |
| 264 // FIXME: Support body. | |
| 265 ResourceRequest request(m_request->url()); | |
| 266 request.setRequestContext(blink::WebURLRequest::RequestContextFetch); | |
| 267 request.setDownloadToFile(true); | |
| 268 request.setHTTPMethod(m_request->method()); | |
| 269 const Vector<OwnPtr<FetchHeaderList::Header> >& list = m_request->headerList ()->list(); | |
| 270 for (size_t i = 0; i < list.size(); ++i) { | |
| 271 request.addHTTPHeaderField(AtomicString(list[i]->first), AtomicString(li st[i]->second)); | |
| 272 } | |
| 273 | |
| 274 // "2. Append `Referer`/empty byte sequence, if |HTTPRequest|'s |referrer| | |
| 275 // is none, and `Referer`/|HTTPRequest|'s referrer, serialized and utf-8 | |
| 276 // encoded, otherwise, to HTTPRequest's header list. | |
| 277 // We set the referrer using workerGlobalScope's URL in | |
| 278 // WorkerThreadableLoader. | |
| 279 | |
| 280 // "3. Append `Host`, ..." | |
| 281 // FIXME: Implement this when the spec is fixed. | |
| 282 | |
| 283 // "4.If |HTTPRequest|'s force Origin header flag is set, append `Origin`/ | |
| 284 // |HTTPRequest|'s origin, serialized and utf-8 encoded, to |HTTPRequest|'s | |
| 285 // header list." | |
| 286 // We set Origin header in updateRequestForAccessControl() called from | |
| 287 // DocumentThreadableLoader::makeCrossOriginAccessRequest | |
| 288 | |
| 289 // "5. Let |credentials flag| be set if either |HTTPRequest|'s credentials | |
| 290 // mode is |include|, or |HTTPRequest|'s credentials mode is |same-origin| | |
| 291 // and the |CORS flag| is unset, and unset otherwise. | |
| 292 ResourceLoaderOptions resourceLoaderOptions; | |
| 293 resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData; | |
| 294 if (m_request->credentials() == FetchRequestData::IncludeCredentials | |
| 295 || (m_request->credentials() == FetchRequestData::SameOriginCredentials && !m_corsFlag)) { | |
| 296 resourceLoaderOptions.allowCredentials = AllowStoredCredentials; | |
| 297 } | |
| 298 | |
| 299 ThreadableLoaderOptions threadableLoaderOptions; | |
| 300 if (m_corsPreflightFlag) | |
| 301 threadableLoaderOptions.preflightPolicy = ForcePreflight; | |
| 302 if (m_corsFlag) | |
| 303 threadableLoaderOptions.crossOriginRequestPolicy = UseAccessControl; | |
| 304 else | |
| 305 threadableLoaderOptions.crossOriginRequestPolicy = AllowCrossOriginReque sts; | |
| 306 | |
| 307 | |
| 308 m_loader = ThreadableLoader::create(*m_executionContext, this, request, thre adableLoaderOptions, resourceLoaderOptions); | |
| 309 } | |
| 310 | |
| 136 void FetchManager::Loader::failed() | 311 void FetchManager::Loader::failed() |
| 137 { | 312 { |
| 138 if (m_failed) | 313 if (m_failed) |
| 139 return; | 314 return; |
| 140 m_failed = true; | 315 m_failed = true; |
| 141 ScriptState* state = m_resolver->scriptState(); | 316 ScriptState* state = m_resolver->scriptState(); |
| 142 ScriptState::Scope scope(state); | 317 ScriptState::Scope scope(state); |
| 143 m_resolver->reject(V8ThrowException::createTypeError("Failed to fetch", stat e->isolate())); | 318 m_resolver->reject(V8ThrowException::createTypeError("Failed to fetch", stat e->isolate())); |
| 144 notifyFinished(); | 319 notifyFinished(); |
| 145 } | 320 } |
| 146 | 321 |
| 147 void FetchManager::Loader::notifyFinished() | 322 void FetchManager::Loader::notifyFinished() |
| 148 { | 323 { |
| 149 if (m_fetchManager) | 324 if (m_fetchManager) |
| 150 m_fetchManager->onLoaderFinished(this); | 325 m_fetchManager->onLoaderFinished(this); |
| 151 } | 326 } |
| 152 | 327 |
| 153 FetchManager::FetchManager(ExecutionContext* executionContext) | 328 FetchManager::FetchManager(ExecutionContext* executionContext) |
| 154 : m_executionContext(executionContext) | 329 : m_executionContext(executionContext) |
| 155 { | 330 { |
| 156 } | 331 } |
| 157 | 332 |
| 158 FetchManager::~FetchManager() | 333 FetchManager::~FetchManager() |
| 159 { | 334 { |
| 160 for (HashSet<OwnPtr<Loader> >::iterator it = m_loaders.begin(); it != m_load ers.end(); ++it) { | 335 for (HashSet<OwnPtr<Loader> >::iterator it = m_loaders.begin(); it != m_load ers.end(); ++it) { |
| 161 (*it)->cleanup(); | 336 (*it)->cleanup(); |
| 162 } | 337 } |
| 163 } | 338 } |
| 164 | 339 |
| 165 ScriptPromise FetchManager::fetch(ScriptState* scriptState, PassOwnPtr<ResourceR equest> request) | 340 ScriptPromise FetchManager::fetch(ScriptState* scriptState, PassRefPtr<FetchRequ estData> request) |
| 166 { | 341 { |
| 167 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scrip tState); | 342 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scrip tState); |
| 168 ScriptPromise promise = resolver->promise(); | 343 ScriptPromise promise = resolver->promise(); |
| 169 | 344 |
| 170 OwnPtr<Loader> loader(adoptPtr(new Loader(m_executionContext, this, resolver .release(), request))); | 345 OwnPtr<Loader> ownLoader(adoptPtr(new Loader(m_executionContext, this, resol ver.release(), request))); |
| 171 (*m_loaders.add(loader.release()).storedValue)->start(); | 346 Loader* loader = m_loaders.add(ownLoader.release()).storedValue->get(); |
| 347 loader->start(); | |
| 172 return promise; | 348 return promise; |
| 173 } | 349 } |
| 174 | 350 |
| 175 void FetchManager::onLoaderFinished(Loader* loader) | 351 void FetchManager::onLoaderFinished(Loader* loader) |
| 176 { | 352 { |
| 177 m_loaders.remove(loader); | 353 m_loaders.remove(loader); |
| 178 } | 354 } |
| 179 | 355 |
| 180 bool FetchManager::isSimpleMethod(const String& method) | 356 bool FetchManager::isSimpleMethod(const String& method) |
| 181 { | 357 { |
| 182 // "A simple method is a method that is `GET`, `HEAD`, or `POST`." | 358 // "A simple method is a method that is `GET`, `HEAD`, or `POST`." |
| 183 return isOnAccessControlSimpleRequestMethodWhitelist(method); | 359 return isOnAccessControlSimpleRequestMethodWhitelist(method); |
| 184 } | 360 } |
| 185 | 361 |
| 186 bool FetchManager::isForbiddenMethod(const String& method) | 362 bool FetchManager::isForbiddenMethod(const String& method) |
| 187 { | 363 { |
| 188 // "A forbidden method is a method that is a byte case-insensitive match for one of `CONNECT`, `TRACE`, and `TRACK`." | 364 // "A forbidden method is a method that is a byte case-insensitive match for |
| 365 // one of `CONNECT`, `TRACE`, and `TRACK`." | |
| 189 return !XMLHttpRequest::isAllowedHTTPMethod(method); | 366 return !XMLHttpRequest::isAllowedHTTPMethod(method); |
| 190 } | 367 } |
| 191 | 368 |
| 192 bool FetchManager::isUsefulMethod(const String& method) | 369 bool FetchManager::isUsefulMethod(const String& method) |
| 193 { | 370 { |
| 194 // "A useful method is a method that is not a forbidden method." | 371 // "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`." | 372 // "A forbidden method is a method that is a byte case-insensitive match for |
| 373 // one of `CONNECT`, `TRACE`, and `TRACK`." | |
| 196 return XMLHttpRequest::isAllowedHTTPMethod(method); | 374 return XMLHttpRequest::isAllowedHTTPMethod(method); |
| 197 } | 375 } |
| 198 | 376 |
| 199 } // namespace blink | 377 } // namespace blink |
| OLD | NEW |