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 "modules/fetch/Headers.h" | 5 #include "modules/fetch/Headers.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/Dictionary.h" | 7 #include "bindings/core/v8/Dictionary.h" |
| 8 #include "bindings/core/v8/ExceptionState.h" | 8 #include "bindings/core/v8/ExceptionState.h" |
| 9 #include "bindings/core/v8/V8IteratorResultValue.h" | 9 #include "bindings/core/v8/V8IteratorResultValue.h" |
| 10 #include "bindings/modules/v8/ByteStringSequenceSequenceOrDictionaryOrHeaders.h" | |
| 10 #include "core/dom/Iterator.h" | 11 #include "core/dom/Iterator.h" |
| 11 #include "platform/loader/fetch/FetchUtils.h" | 12 #include "platform/loader/fetch/FetchUtils.h" |
| 12 #include "wtf/NotFound.h" | 13 #include "wtf/NotFound.h" |
| 13 #include "wtf/PassRefPtr.h" | 14 #include "wtf/PassRefPtr.h" |
| 14 #include "wtf/RefPtr.h" | 15 #include "wtf/RefPtr.h" |
| 15 #include "wtf/text/WTFString.h" | 16 #include "wtf/text/WTFString.h" |
| 16 | 17 |
| 17 namespace blink { | 18 namespace blink { |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 47 PairIterable<String, String>::IterationSource::trace(visitor); | 48 PairIterable<String, String>::IterationSource::trace(visitor); |
| 48 } | 49 } |
| 49 | 50 |
| 50 private: | 51 private: |
| 51 const Member<FetchHeaderList> m_headers; | 52 const Member<FetchHeaderList> m_headers; |
| 52 size_t m_current; | 53 size_t m_current; |
| 53 }; | 54 }; |
| 54 | 55 |
| 55 } // namespace | 56 } // namespace |
| 56 | 57 |
| 57 Headers* Headers::create() { | 58 Headers* Headers::create(ExceptionState&) { |
| 58 return new Headers; | 59 return new Headers; |
| 59 } | 60 } |
| 60 | 61 |
| 61 Headers* Headers::create(ExceptionState&) { | 62 Headers* Headers::create( |
| 62 return create(); | 63 const ByteStringSequenceSequenceOrDictionaryOrHeaders& init, |
| 63 } | 64 ExceptionState& exceptionState) { |
| 64 | |
| 65 Headers* Headers::create(const Headers* init, ExceptionState& exceptionState) { | |
| 66 // "The Headers(|init|) constructor, when invoked, must run these steps:" | 65 // "The Headers(|init|) constructor, when invoked, must run these steps:" |
| 67 // "1. Let |headers| be a new Headers object." | 66 // "1. Let |headers| be a new Headers object whose guard is "none". |
| 68 Headers* headers = create(); | 67 Headers* headers = create(exceptionState); |
| 69 // "2. If |init| is given, fill headers with |init|. Rethrow any exception." | 68 // "2. If |init| is given, fill headers with |init|. Rethrow any exception." |
| 70 headers->fillWith(init, exceptionState); | 69 if (init.isByteStringSequenceSequence()) { |
| 70 headers->fillWith(init.getAsByteStringSequenceSequence(), exceptionState); | |
| 71 } else if (init.isDictionary()) { | |
| 72 headers->fillWith(init.getAsDictionary(), exceptionState); | |
| 73 } else if (init.isHeaders()) { | |
| 74 // This branch will not be necessary once http://crbug.com/690428 is fixed. | |
| 75 headers->fillWith(init.getAsHeaders(), exceptionState); | |
| 76 } | |
| 71 // "3. Return |headers|." | 77 // "3. Return |headers|." |
| 72 return headers; | 78 return headers; |
| 73 } | 79 } |
| 74 | |
| 75 Headers* Headers::create(const Vector<Vector<String>>& init, | |
| 76 ExceptionState& exceptionState) { | |
| 77 // The same steps as above. | |
| 78 Headers* headers = create(); | |
| 79 headers->fillWith(init, exceptionState); | |
| 80 return headers; | |
| 81 } | |
| 82 | |
| 83 Headers* Headers::create(const Dictionary& init, | |
| 84 ExceptionState& exceptionState) { | |
| 85 // "The Headers(|init|) constructor, when invoked, must run these steps:" | |
| 86 // "1. Let |headers| be a new Headers object." | |
| 87 Headers* headers = create(); | |
| 88 // "2. If |init| is given, fill headers with |init|. Rethrow any exception." | |
| 89 headers->fillWith(init, exceptionState); | |
| 90 // "3. Return |headers|." | |
| 91 return headers; | |
| 92 } | |
| 93 | 80 |
| 94 Headers* Headers::create(FetchHeaderList* headerList) { | 81 Headers* Headers::create(FetchHeaderList* headerList) { |
| 95 return new Headers(headerList); | 82 return new Headers(headerList); |
| 96 } | 83 } |
| 97 | 84 |
| 98 Headers* Headers::clone() const { | 85 Headers* Headers::clone() const { |
| 99 FetchHeaderList* headerList = m_headerList->clone(); | 86 FetchHeaderList* headerList = m_headerList->clone(); |
| 100 Headers* headers = create(headerList); | 87 Headers* headers = create(headerList); |
| 101 headers->m_guard = m_guard; | 88 headers->m_guard = m_guard; |
| 102 return headers; | 89 return headers; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 244 // header name, return." | 231 // header name, return." |
| 245 if (m_guard == ResponseGuard && | 232 if (m_guard == ResponseGuard && |
| 246 FetchUtils::isForbiddenResponseHeaderName(name)) | 233 FetchUtils::isForbiddenResponseHeaderName(name)) |
| 247 return; | 234 return; |
| 248 // "6. Set |name|/|value| in header list." | 235 // "6. Set |name|/|value| in header list." |
| 249 m_headerList->set(name, value); | 236 m_headerList->set(name, value); |
| 250 } | 237 } |
| 251 | 238 |
| 252 void Headers::fillWith(const Headers* object, ExceptionState& exceptionState) { | 239 void Headers::fillWith(const Headers* object, ExceptionState& exceptionState) { |
| 253 ASSERT(m_headerList->size() == 0); | 240 ASSERT(m_headerList->size() == 0); |
| 254 // "To fill a Headers object (|this|) with a given object (|object|), run | 241 // There used to be specific steps describing filling a Headers object with |
| 255 // these steps:" | 242 // another Headers object, but it has since been removed because it should be |
| 256 // "1. If |object| is a Headers object, copy its header list as | 243 // handled like a sequence (http://crbug.com/690428). |
| 257 // |headerListCopy| and then for each |header| in |headerListCopy|, | |
| 258 // retaining order, append header's |name|/|header|'s value to | |
| 259 // |headers|. Rethrow any exception." | |
| 260 for (size_t i = 0; i < object->m_headerList->list().size(); ++i) { | 244 for (size_t i = 0; i < object->m_headerList->list().size(); ++i) { |
| 261 append(object->m_headerList->list()[i]->first, | 245 append(object->m_headerList->list()[i]->first, |
| 262 object->m_headerList->list()[i]->second, exceptionState); | 246 object->m_headerList->list()[i]->second, exceptionState); |
| 263 if (exceptionState.hadException()) | 247 if (exceptionState.hadException()) |
| 264 return; | 248 return; |
| 265 } | 249 } |
| 266 } | 250 } |
| 267 | 251 |
| 268 void Headers::fillWith(const Vector<Vector<String>>& object, | 252 void Headers::fillWith(const Vector<Vector<String>>& object, |
| 269 ExceptionState& exceptionState) { | 253 ExceptionState& exceptionState) { |
| 270 ASSERT(!m_headerList->size()); | 254 ASSERT(!m_headerList->size()); |
| 271 // "2. Otherwise, if |object| is a sequence, then for each |header| in | 255 // "1. If |object| is a sequence, then for each |header| in |object|, run |
| 272 // |object|, run these substeps: | 256 // these substeps: |
| 273 // 1. If |header| does not contain exactly two items, throw a | 257 // 1. If |header| does not contain exactly two items, then throw a |
| 274 // TypeError. | 258 // TypeError. |
| 275 // 2. Append |header|'s first item/|header|'s second item to | 259 // 2. Append |header|’s first item/|header|’s second item to |headers|. |
| 276 // |headers|. Rethrow any exception." | 260 // Rethrow any exception." |
| 277 for (size_t i = 0; i < object.size(); ++i) { | 261 for (size_t i = 0; i < object.size(); ++i) { |
| 278 if (object[i].size() != 2) { | 262 if (object[i].size() != 2) { |
| 279 exceptionState.throwTypeError("Invalid value"); | 263 exceptionState.throwTypeError("Invalid value"); |
| 280 return; | 264 return; |
| 281 } | 265 } |
| 282 append(object[i][0], object[i][1], exceptionState); | 266 append(object[i][0], object[i][1], exceptionState); |
| 283 if (exceptionState.hadException()) | 267 if (exceptionState.hadException()) |
| 284 return; | 268 return; |
| 285 } | 269 } |
| 286 } | 270 } |
| 287 | 271 |
| 288 void Headers::fillWith(const Dictionary& object, | 272 void Headers::fillWith(const Dictionary& object, |
| 289 ExceptionState& exceptionState) { | 273 ExceptionState& exceptionState) { |
| 290 ASSERT(!m_headerList->size()); | 274 ASSERT(!m_headerList->size()); |
| 291 const Vector<String>& keys = object.getPropertyNames(exceptionState); | 275 const Vector<String>& keys = object.getPropertyNames(exceptionState); |
| 292 if (exceptionState.hadException() || !keys.size()) | 276 if (exceptionState.hadException() || !keys.size()) |
| 293 return; | 277 return; |
| 294 | 278 |
| 295 // "3. Otherwise, if |object| is an open-ended dictionary, then for each | 279 // "2. Otherwise, |object| is a record, then for each mapping (|key|, |
| 296 // |header| in object, run these substeps: | 280 // |value|) in |object|, append |key|/|value| to |headers|. Rethrow any |
| 297 // 1. Set |header|'s key to |header|'s key, converted to ByteString. | 281 // exception." |
| 298 // Rethrow any exception. | 282 // FIXME: This method's signature must change once we support record<K,V> in |
|
yhirano
2017/02/13 05:56:51
TODO(rakuco):
| |
| 299 // 2. Append |header|'s key/|header|'s value to |headers|. Rethrow any | 283 // the WebIDL code (http://crbug.com/685754). |
| 300 // exception." | |
| 301 // FIXME: Support OpenEndedDictionary<ByteString>. | |
| 302 for (size_t i = 0; i < keys.size(); ++i) { | 284 for (size_t i = 0; i < keys.size(); ++i) { |
| 303 String value; | 285 String value; |
| 304 if (!DictionaryHelper::get(object, keys[i], value)) { | 286 if (!DictionaryHelper::get(object, keys[i], value)) { |
| 305 exceptionState.throwTypeError("Invalid value"); | 287 exceptionState.throwTypeError("Invalid value"); |
| 306 return; | 288 return; |
| 307 } | 289 } |
| 308 append(keys[i], value, exceptionState); | 290 append(keys[i], value, exceptionState); |
| 309 if (exceptionState.hadException()) | 291 if (exceptionState.hadException()) |
| 310 return; | 292 return; |
| 311 } | 293 } |
| 312 } | 294 } |
| 313 | 295 |
| 314 Headers::Headers() | 296 Headers::Headers() |
| 315 : m_headerList(FetchHeaderList::create()), m_guard(NoneGuard) {} | 297 : m_headerList(FetchHeaderList::create()), m_guard(NoneGuard) {} |
| 316 | 298 |
| 317 Headers::Headers(FetchHeaderList* headerList) | 299 Headers::Headers(FetchHeaderList* headerList) |
| 318 : m_headerList(headerList), m_guard(NoneGuard) {} | 300 : m_headerList(headerList), m_guard(NoneGuard) {} |
| 319 | 301 |
| 320 DEFINE_TRACE(Headers) { | 302 DEFINE_TRACE(Headers) { |
| 321 visitor->trace(m_headerList); | 303 visitor->trace(m_headerList); |
| 322 } | 304 } |
| 323 | 305 |
| 324 PairIterable<String, String>::IterationSource* Headers::startIteration( | 306 PairIterable<String, String>::IterationSource* Headers::startIteration( |
| 325 ScriptState*, | 307 ScriptState*, |
| 326 ExceptionState&) { | 308 ExceptionState&) { |
| 327 return new HeadersIterationSource(m_headerList); | 309 return new HeadersIterationSource(m_headerList); |
| 328 } | 310 } |
| 329 | 311 |
| 330 } // namespace blink | 312 } // namespace blink |
| OLD | NEW |