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

Side by Side Diff: Source/modules/serviceworkers/Headers.cpp

Issue 358573002: [ServiceWorker] Implement Headers class. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: 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
« no previous file with comments | « Source/modules/serviceworkers/Headers.h ('k') | Source/modules/serviceworkers/Headers.idl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "modules/serviceworkers/Headers.h"
7
8 #include "bindings/v8/Dictionary.h"
9 #include "bindings/v8/ExceptionState.h"
10 #include "core/fetch/CrossOriginAccessControl.h"
11 #include "core/xml/XMLHttpRequest.h"
12 #include "modules/serviceworkers/FetchManager.h"
yhirano 2014/06/26 08:55:10 Do you need this include?
horo 2014/06/26 09:16:52 deleted.
13 #include "modules/serviceworkers/HeadersForEachCallback.h"
14 #include "wtf/NotFound.h"
15 #include "wtf/PassRefPtr.h"
16 #include "wtf/RefPtr.h"
17 #include "wtf/text/WTFString.h"
18
19 namespace WebCore {
20
21 PassRefPtr<Headers> Headers::create()
22 {
23 return adoptRef(new Headers);
24 }
25
26 PassRefPtr<Headers> Headers::create(ExceptionState&)
27 {
28 return create();
29 }
30
31 PassRefPtr<Headers> Headers::create(const Headers* input, ExceptionState& except ionState)
32 {
33 // The Headers(init) constructor, when invoked, must run these steps:
34 // 1. Let headers be a new Headers object.
35 RefPtr<Headers> headers = create();
36 // 2. If init is given, fill headers with init. Rethrow any exception.
37 headers->fillWith(input, exceptionState);
38 // 3. Return headers.
39 return headers.release();
40 }
41
42 PassRefPtr<Headers> Headers::create(const Dictionary& input, ExceptionState& exc eptionState)
43 {
44 // The Headers(init) constructor, when invoked, must run these steps:
45 // 1. Let headers be a new Headers object.
46 RefPtr<Headers> headers = create();
47 // 2. If init is given, fill headers with init. Rethrow any exception.
48 headers->fillWith(input, exceptionState);
49 // 3. Return headers.
50 return headers.release();
51 }
52
53 // Called when creating Request.
54 PassRefPtr<Headers> Headers::create(FetchHeaderList* headerList)
55 {
56 return adoptRef(new Headers(headerList));
57 }
58
59 Headers::~Headers()
60 {
61 }
62
63 unsigned long Headers::size() const
64 {
65 return m_headerList->size();
66 }
67
68 void Headers::append(const String& name, const String& value, ExceptionState& ex ceptionState)
69 {
70 // To append a name/value (name/value) pair to a Headers object (headers),
71 // run these steps:
72 // 1. If name is not a name or value is not a value, throw a TypeError.
73 if (!FetchHeaderList::isValidHeaderName(name)) {
74 exceptionState.throwTypeError("Invalid name");
75 return;
76 }
77 if (!FetchHeaderList::isValidHeaderValue(value)) {
78 exceptionState.throwTypeError("Invalid value");
79 return;
80 }
81 // 2. If guard is immutable, throw a TypeError.
82 if (m_guard == ImmutableGuard) {
83 exceptionState.throwTypeError("Headers are immutable");
84 return;
85 }
86 // 3. Otherwise, if guard is request and name is a forbidden header name,
87 // return.
88 if (m_guard == RequestGuard && FetchHeaderList::isForbiddenHeaderName(name))
89 return;
90 // 4. Otherwise, if guard is request-no-CORS and name/value is not a simple
91 // header, return.
92 if (m_guard == RequestNoCORSGuard && !FetchHeaderList::isSimpleHeader(name, value))
93 return;
94 // 5. Otherwise, if guard is response and name is a forbidden response
95 // header name, return.
96 if (m_guard == ResponseGuard && FetchHeaderList::isForbiddenResponseHeaderNa me(name))
97 return;
98 // 6. Append name/value to header list.
99 m_headerList->append(name, value);
100 }
101
102 void Headers::remove(const String& name, ExceptionState& exceptionState)
103 {
104 // The delete(name) method, when invoked, must run these steps:
105 // 1. If name is not a name, throw a TypeError.
106 if (!FetchHeaderList::isValidHeaderName(name)) {
107 exceptionState.throwTypeError("Invalid name");
108 return;
109 }
110 // 2. If guard is immutable, throw a TypeError.
111 if (m_guard == ImmutableGuard) {
112 exceptionState.throwTypeError("Headers are immutable");
113 return;
114 }
115 // 3. Otherwise, if guard is request and name is a forbidden header name,
116 // return.
117 if (m_guard == RequestGuard && FetchHeaderList::isForbiddenHeaderName(name))
118 return;
119 // 4. Otherwise, if guard is request-no-CORS and name/value is not a simple
120 // header, return.
121 if (m_guard == RequestNoCORSGuard && !FetchHeaderList::isSimpleHeader(name, "invalid"))
122 return;
123 // 5. Otherwise, if guard is response and name is a forbidden response
124 // header name, return.
125 if (m_guard == ResponseGuard && FetchHeaderList::isForbiddenResponseHeaderNa me(name))
126 return;
127 // 6. Remove all headers whose name is name from header list.
128 m_headerList->remove(name);
129 }
130
131 String Headers::get(const String& name, ExceptionState& exceptionState)
132 {
133 // The get(name) method, when invoked, must run these steps:
134 // 1. If name is not a name, throw a TypeError.
135 if (!FetchHeaderList::isValidHeaderName(name)) {
136 exceptionState.throwTypeError("Invalid name");
137 return String();
138 }
139 // 2. Return the value of the first header in header list whose name is
140 // name, and null otherwise.
141 String result;
142 if (m_headerList->get(name, result))
143 return result;
144 return String();
145 }
146
147 Vector<String> Headers::getAll(const String& name, ExceptionState& exceptionStat e)
148 {
149 // The getAll(name) method, when invoked, must run these steps:
150 // 1. If name is not a name, throw a TypeError.
151 if (!FetchHeaderList::isValidHeaderName(name)) {
152 exceptionState.throwTypeError("Invalid name");
153 return Vector<String>();
154 }
155 // 2. Return the values of all headers in header list whose name is name, in
156 // list order, and the empty sequence otherwise.
157 Vector<String> result;
158 m_headerList->getAll(name, result);
159 return result;
160 }
161
162 bool Headers::has(const String& name, ExceptionState& exceptionState)
163 {
164 // The has(name) method, when invoked, must run these steps:
165 // 1. If name is not a name, throw a TypeError.
166 if (!FetchHeaderList::isValidHeaderName(name)) {
167 exceptionState.throwTypeError("Invalid name");
168 return false;
169 }
170 // 2. Return true if there is a header in header list whose name is name,
171 // and false otherwise.
172 return m_headerList->has(name);
173 }
174
175 void Headers::set(const String& name, const String& value, ExceptionState& excep tionState)
176 {
177 // The set(name, value) method, when invoked, must run these steps:
178 // 1. If name is not a name or value is not a value, throw a TypeError.
179 if (!FetchHeaderList::isValidHeaderName(name)) {
180 exceptionState.throwTypeError("Invalid name");
181 return;
182 }
183 if (!FetchHeaderList::isValidHeaderValue(value)) {
184 exceptionState.throwTypeError("Invalid value");
185 return;
186 }
187 // 2. If guard is immutable, throw a TypeError.
188 if (m_guard == ImmutableGuard) {
189 exceptionState.throwTypeError("Headers are immutable");
190 return;
191 }
192 // 3. Otherwise, if guard is request and name is a forbidden header name,
193 // return.
194 if (m_guard == RequestGuard && FetchHeaderList::isForbiddenHeaderName(name))
195 return;
196 // 4. Otherwise, if guard is request-no-CORS and name/value is not a simple
197 // header, return.
198 if (m_guard == RequestNoCORSGuard && !FetchHeaderList::isSimpleHeader(name, value))
199 return;
200 // 5. Otherwise, if guard is response and name is a forbidden response
201 // header name, return.
202 if (m_guard == ResponseGuard && FetchHeaderList::isForbiddenResponseHeaderNa me(name))
203 return;
204 // 6. Set name/value in header list.
205 m_headerList->set(name, value);
206 }
207
208 void Headers::forEach(PassOwnPtr<HeadersForEachCallback> callback, ScriptValue& thisArg)
209 {
210 forEachInternal(callback, &thisArg);
211 }
212
213 void Headers::forEach(PassOwnPtr<HeadersForEachCallback> callback)
214 {
215 forEachInternal(callback, 0);
216 }
217
218 void Headers::fillWith(const Headers* headers, ExceptionState& exceptionState)
219 {
220 ASSERT(m_headerList->size() == 0);
221 // To fill a Headers object (headers) with a given object (object), run
222 // these steps:
223 // 1. If object is a Headers object, copy its header list as headerListCopy
224 // and then for each header in headerListCopy, retaining order, append
225 // header's name/header's value to headers. Rethrow any exception.
226 for (size_t i = 0; i < headers->m_headerList->list().size(); ++i) {
227 append(headers->m_headerList->list()[i]->first, headers->m_headerList->l ist()[i]->second, exceptionState);
228 if (exceptionState.hadException())
229 return;
230 }
231 }
232
233 void Headers::fillWith(const Dictionary& dictionary, ExceptionState& exceptionSt ate)
234 {
235 ASSERT(m_headerList->size() == 0);
236 Vector<String> keys;
237 dictionary.getOwnPropertyNames(keys);
238 if (keys.size() == 0)
239 return;
240
241 // Because of the restrictions in IDL compiler of blink we recieve
242 // sequence<sequence<ByteString>> as a Dictionary, which is a type of union
243 // type of HeadersInit defined in the spec.
244 // http://fetch.spec.whatwg.org/#headers-class
245 // FIXME: Support sequence<sequence<ByteString>>.
246 Vector<String> keyValuePair;
247 if (dictionary.get(keys[0], keyValuePair)) {
248 // 2. Otherwise, if object is a sequence, then for each header in
249 // object, run these substeps:
250 // 1. If header does not contain two items, throw a TypeError.
251 // 2. Append header's first item/header's second time to headers.
252 // Rethrow any exception.
253 for (size_t i = 0; i < keys.size(); ++i) {
254 // We've already got the keyValuePair for key[0].
255 if (i > 0) {
256 if (!dictionary.get(keys[i], keyValuePair)) {
257 exceptionState.throwTypeError("Invalid value");
258 return;
259 }
260 }
261 if (keyValuePair.size() < 2) {
262 exceptionState.throwTypeError("Invalid value");
263 return;
264 }
265 append(keyValuePair[0], keyValuePair[1], exceptionState);
266 if (exceptionState.hadException())
267 return;
268 keyValuePair.clear();
269 }
270 return;
271 }
272 // 3. Otherwise, if object is an open-ended dictionary, then for each header
273 // in object, run these substeps:
274 // 1. Set header's key to header's key, converted to ByteString. Rethrow
275 // any exception.
276 // 2. Append header's key/header's value to headers. Rethrow any
277 // exception.
278 // FIXME: Support OpenEndedDictionary<ByteString>.
279 for (size_t i = 0; i < keys.size(); ++i) {
280 String value;
281 if (!dictionary.get(keys[i], value)) {
282 exceptionState.throwTypeError("Invalid value");
283 return;
284 }
285 append(keys[i], value, exceptionState);
286 if (exceptionState.hadException())
287 return;
288 }
289 }
290
291 Headers::Headers()
292 : m_headerList(FetchHeaderList::create())
293 , m_guard(NoneGuard)
294 {
295 ScriptWrappable::init(this);
296 }
297
298 // Called when creating Request or Responce.
299 Headers::Headers(FetchHeaderList* headerList)
300 : m_headerList(headerList)
301 , m_guard(NoneGuard)
302 {
303 ScriptWrappable::init(this);
304 }
305
306 void Headers::forEachInternal(PassOwnPtr<HeadersForEachCallback> callback, Scrip tValue* thisArg)
307 {
308 TrackExceptionState exceptionState;
309 for (size_t i = 0; i < m_headerList->size(); ++i) {
310 if (thisArg)
311 callback->handleItem(*thisArg, m_headerList->list()[i]->second, m_he aderList->list()[i]->first, this);
312 else
313 callback->handleItem(m_headerList->list()[i]->second, m_headerList-> list()[i]->first, this);
314 if (exceptionState.hadException())
315 break;
316 }
317 }
318
319 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/modules/serviceworkers/Headers.h ('k') | Source/modules/serviceworkers/Headers.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698