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" | |
8 #include "bindings/core/v8/ExceptionState.h" | 7 #include "bindings/core/v8/ExceptionState.h" |
9 #include "bindings/core/v8/V8IteratorResultValue.h" | 8 #include "bindings/core/v8/V8IteratorResultValue.h" |
| 9 #include "bindings/modules/v8/ByteStringSequenceSequenceOrByteStringByteStringRe
cordOrHeaders.h" |
10 #include "core/dom/Iterator.h" | 10 #include "core/dom/Iterator.h" |
11 #include "platform/loader/fetch/FetchUtils.h" | 11 #include "platform/loader/fetch/FetchUtils.h" |
12 #include "platform/wtf/NotFound.h" | 12 #include "platform/wtf/NotFound.h" |
13 #include "platform/wtf/PassRefPtr.h" | 13 #include "platform/wtf/PassRefPtr.h" |
14 #include "platform/wtf/RefPtr.h" | 14 #include "platform/wtf/RefPtr.h" |
15 #include "platform/wtf/text/WTFString.h" | 15 #include "platform/wtf/text/WTFString.h" |
16 | 16 |
17 namespace blink { | 17 namespace blink { |
18 | 18 |
19 namespace { | 19 namespace { |
(...skipping 27 matching lines...) Expand all Loading... |
47 PairIterable<String, String>::IterationSource::Trace(visitor); | 47 PairIterable<String, String>::IterationSource::Trace(visitor); |
48 } | 48 } |
49 | 49 |
50 private: | 50 private: |
51 const Member<FetchHeaderList> headers_; | 51 const Member<FetchHeaderList> headers_; |
52 size_t current_; | 52 size_t current_; |
53 }; | 53 }; |
54 | 54 |
55 } // namespace | 55 } // namespace |
56 | 56 |
57 Headers* Headers::Create() { | 57 Headers* Headers::Create(ExceptionState&) { |
58 return new Headers; | 58 return new Headers; |
59 } | 59 } |
60 | 60 |
61 Headers* Headers::Create(ExceptionState&) { | 61 Headers* Headers::Create( |
62 return Create(); | 62 const ByteStringSequenceSequenceOrByteStringByteStringRecordOrHeaders& init, |
63 } | 63 ExceptionState& exception_state) { |
64 | |
65 Headers* Headers::Create(const Headers* init, ExceptionState& exception_state) { | |
66 // "The Headers(|init|) constructor, when invoked, must run these steps:" | 64 // "The Headers(|init|) constructor, when invoked, must run these steps:" |
67 // "1. Let |headers| be a new Headers object." | 65 // "1. Let |headers| be a new Headers object whose guard is "none". |
68 Headers* headers = Create(); | 66 Headers* headers = Create(exception_state); |
69 // "2. If |init| is given, fill headers with |init|. Rethrow any exception." | 67 // "2. If |init| is given, fill headers with |init|. Rethrow any exception." |
70 headers->FillWith(init, exception_state); | 68 if (init.isByteStringSequenceSequence()) { |
| 69 headers->FillWith(init.getAsByteStringSequenceSequence(), exception_state); |
| 70 } else if (init.isByteStringByteStringRecord()) { |
| 71 headers->FillWith(init.getAsByteStringByteStringRecord(), exception_state); |
| 72 } else if (init.isHeaders()) { |
| 73 // This branch will not be necessary once http://crbug.com/690428 is fixed. |
| 74 headers->FillWith(init.getAsHeaders(), exception_state); |
| 75 } else { |
| 76 NOTREACHED(); |
| 77 } |
71 // "3. Return |headers|." | 78 // "3. Return |headers|." |
72 return headers; | 79 return headers; |
73 } | 80 } |
74 | |
75 Headers* Headers::Create(const Vector<Vector<String>>& init, | |
76 ExceptionState& exception_state) { | |
77 // The same steps as above. | |
78 Headers* headers = Create(); | |
79 headers->FillWith(init, exception_state); | |
80 return headers; | |
81 } | |
82 | |
83 Headers* Headers::Create(const Dictionary& init, | |
84 ExceptionState& exception_state) { | |
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, exception_state); | |
90 // "3. Return |headers|." | |
91 return headers; | |
92 } | |
93 | 81 |
94 Headers* Headers::Create(FetchHeaderList* header_list) { | 82 Headers* Headers::Create(FetchHeaderList* header_list) { |
95 return new Headers(header_list); | 83 return new Headers(header_list); |
96 } | 84 } |
97 | 85 |
98 Headers* Headers::Clone() const { | 86 Headers* Headers::Clone() const { |
99 FetchHeaderList* header_list = header_list_->Clone(); | 87 FetchHeaderList* header_list = header_list_->Clone(); |
100 Headers* headers = Create(header_list); | 88 Headers* headers = Create(header_list); |
101 headers->guard_ = guard_; | 89 headers->guard_ = guard_; |
102 return headers; | 90 return headers; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 // header name, return." | 232 // header name, return." |
245 if (guard_ == kResponseGuard && | 233 if (guard_ == kResponseGuard && |
246 FetchUtils::IsForbiddenResponseHeaderName(name)) | 234 FetchUtils::IsForbiddenResponseHeaderName(name)) |
247 return; | 235 return; |
248 // "6. Set |name|/|value| in header list." | 236 // "6. Set |name|/|value| in header list." |
249 header_list_->Set(name, value); | 237 header_list_->Set(name, value); |
250 } | 238 } |
251 | 239 |
252 void Headers::FillWith(const Headers* object, ExceptionState& exception_state) { | 240 void Headers::FillWith(const Headers* object, ExceptionState& exception_state) { |
253 ASSERT(header_list_->size() == 0); | 241 ASSERT(header_list_->size() == 0); |
254 // "To fill a Headers object (|this|) with a given object (|object|), run | 242 // There used to be specific steps describing filling a Headers object with |
255 // these steps:" | 243 // 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 | 244 // 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->header_list_->List().size(); ++i) { | 245 for (size_t i = 0; i < object->header_list_->List().size(); ++i) { |
261 append(object->header_list_->List()[i]->first, | 246 append(object->header_list_->List()[i]->first, |
262 object->header_list_->List()[i]->second, exception_state); | 247 object->header_list_->List()[i]->second, exception_state); |
263 if (exception_state.HadException()) | 248 if (exception_state.HadException()) |
264 return; | 249 return; |
265 } | 250 } |
266 } | 251 } |
267 | 252 |
268 void Headers::FillWith(const Vector<Vector<String>>& object, | 253 void Headers::FillWith(const Vector<Vector<String>>& object, |
269 ExceptionState& exception_state) { | 254 ExceptionState& exception_state) { |
270 ASSERT(!header_list_->size()); | 255 ASSERT(!header_list_->size()); |
271 // "2. Otherwise, if |object| is a sequence, then for each |header| in | 256 // "1. If |object| is a sequence, then for each |header| in |object|, run |
272 // |object|, run these substeps: | 257 // these substeps: |
273 // 1. If |header| does not contain exactly two items, throw a | 258 // 1. If |header| does not contain exactly two items, then throw a |
274 // TypeError. | 259 // TypeError. |
275 // 2. Append |header|'s first item/|header|'s second item to | 260 // 2. Append |header|’s first item/|header|’s second item to |headers|. |
276 // |headers|. Rethrow any exception." | 261 // Rethrow any exception." |
277 for (size_t i = 0; i < object.size(); ++i) { | 262 for (size_t i = 0; i < object.size(); ++i) { |
278 if (object[i].size() != 2) { | 263 if (object[i].size() != 2) { |
279 exception_state.ThrowTypeError("Invalid value"); | 264 exception_state.ThrowTypeError("Invalid value"); |
280 return; | 265 return; |
281 } | 266 } |
282 append(object[i][0], object[i][1], exception_state); | 267 append(object[i][0], object[i][1], exception_state); |
283 if (exception_state.HadException()) | 268 if (exception_state.HadException()) |
284 return; | 269 return; |
285 } | 270 } |
286 } | 271 } |
287 | 272 |
288 void Headers::FillWith(const Dictionary& object, | 273 void Headers::FillWith(const Vector<std::pair<String, String>>& object, |
289 ExceptionState& exception_state) { | 274 ExceptionState& exception_state) { |
290 ASSERT(!header_list_->size()); | 275 ASSERT(!header_list_->size()); |
291 const Vector<String>& keys = object.GetPropertyNames(exception_state); | |
292 if (exception_state.HadException() || !keys.size()) | |
293 return; | |
294 | 276 |
295 // "3. Otherwise, if |object| is an open-ended dictionary, then for each | 277 for (const auto& item : object) { |
296 // |header| in object, run these substeps: | 278 append(item.first, item.second, exception_state); |
297 // 1. Set |header|'s key to |header|'s key, converted to ByteString. | |
298 // Rethrow any exception. | |
299 // 2. Append |header|'s key/|header|'s value to |headers|. Rethrow any | |
300 // exception." | |
301 // FIXME: Support OpenEndedDictionary<ByteString>. | |
302 for (size_t i = 0; i < keys.size(); ++i) { | |
303 String value; | |
304 if (!DictionaryHelper::Get(object, keys[i], value)) { | |
305 exception_state.ThrowTypeError("Invalid value"); | |
306 return; | |
307 } | |
308 append(keys[i], value, exception_state); | |
309 if (exception_state.HadException()) | 279 if (exception_state.HadException()) |
310 return; | 280 return; |
311 } | 281 } |
312 } | 282 } |
313 | 283 |
314 Headers::Headers() | 284 Headers::Headers() |
315 : header_list_(FetchHeaderList::Create()), guard_(kNoneGuard) {} | 285 : header_list_(FetchHeaderList::Create()), guard_(kNoneGuard) {} |
316 | 286 |
317 Headers::Headers(FetchHeaderList* header_list) | 287 Headers::Headers(FetchHeaderList* header_list) |
318 : header_list_(header_list), guard_(kNoneGuard) {} | 288 : header_list_(header_list), guard_(kNoneGuard) {} |
319 | 289 |
320 DEFINE_TRACE(Headers) { | 290 DEFINE_TRACE(Headers) { |
321 visitor->Trace(header_list_); | 291 visitor->Trace(header_list_); |
322 } | 292 } |
323 | 293 |
324 PairIterable<String, String>::IterationSource* Headers::StartIteration( | 294 PairIterable<String, String>::IterationSource* Headers::StartIteration( |
325 ScriptState*, | 295 ScriptState*, |
326 ExceptionState&) { | 296 ExceptionState&) { |
327 return new HeadersIterationSource(header_list_); | 297 return new HeadersIterationSource(header_list_); |
328 } | 298 } |
329 | 299 |
330 } // namespace blink | 300 } // namespace blink |
OLD | NEW |