Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / serviceworkers / Response.cpp
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 "Response.h"
7
8 #include "bindings/core/v8/Dictionary.h"
9 #include "bindings/core/v8/ExceptionState.h"
10 #include "core/dom/DOMArrayBuffer.h"
11 #include "core/dom/DOMArrayBufferView.h"
12 #include "core/fileapi/Blob.h"
13 #include "modules/serviceworkers/ResponseInit.h"
14 #include "public/platform/WebServiceWorkerResponse.h"
15 #include "wtf/RefPtr.h"
16
17 namespace blink {
18
19 namespace {
20
21 FetchResponseData* createFetchResponseDataFromWebResponse(const WebServiceWorkerResponse& webResponse)
22 {
23     FetchResponseData* response = 0;
24     if (200 <= webResponse.status() && webResponse.status() < 300)
25         response = FetchResponseData::create();
26     else
27         response = FetchResponseData::createNetworkErrorResponse();
28
29     response->setURL(webResponse.url());
30     response->setStatus(webResponse.status());
31     response->setStatusMessage(webResponse.statusText());
32
33     for (HTTPHeaderMap::const_iterator i = webResponse.headers().begin(), end = webResponse.headers().end(); i != end; ++i) {
34         response->headerList()->append(i->key, i->value);
35     }
36
37     response->setBlobDataHandle(webResponse.blobDataHandle());
38
39     // Filter the response according to |webResponse|'s ResponseType.
40     switch (webResponse.responseType()) {
41     case WebServiceWorkerResponseTypeBasic:
42         response = response->createBasicFilteredResponse();
43         break;
44     case WebServiceWorkerResponseTypeCORS:
45         response = response->createCORSFilteredResponse();
46         break;
47     case WebServiceWorkerResponseTypeOpaque:
48         response = response->createOpaqueFilteredResponse();
49         break;
50     case WebServiceWorkerResponseTypeDefault:
51         break;
52     case WebServiceWorkerResponseTypeError:
53         ASSERT(response->type() == FetchResponseData::ErrorType);
54         break;
55     }
56
57     return response;
58 }
59
60 }
61
62 Response* Response::create(ExecutionContext* context, Blob* body, const Dictionary& responseInit, ExceptionState& exceptionState)
63 {
64     return create(context, body, ResponseInit(responseInit, exceptionState), exceptionState);
65 }
66
67 Response* Response::create(ExecutionContext* context, const String& body, const Dictionary& responseInit, ExceptionState& exceptionState)
68 {
69     OwnPtr<BlobData> blobData = BlobData::create();
70     blobData->appendText(body, false);
71     // "Set |Content-Type| to `text/plain;charset=UTF-8`."
72     blobData->setContentType("text/plain;charset=UTF-8");
73     const long long length = blobData->length();
74     Blob* blob = Blob::create(BlobDataHandle::create(blobData.release(), length));
75     return create(context, blob, ResponseInit(responseInit, exceptionState), exceptionState);
76 }
77
78 Response* Response::create(ExecutionContext* context, const DOMArrayBuffer* body, const Dictionary& responseInit, ExceptionState& exceptionState)
79 {
80     OwnPtr<BlobData> blobData = BlobData::create();
81     blobData->appendArrayBuffer(body->buffer());
82     const long long length = blobData->length();
83     Blob* blob = Blob::create(BlobDataHandle::create(blobData.release(), length));
84     return create(context, blob, ResponseInit(responseInit, exceptionState), exceptionState);
85 }
86
87 Response* Response::create(ExecutionContext* context, const DOMArrayBufferView* body, const Dictionary& responseInit, ExceptionState& exceptionState)
88 {
89     OwnPtr<BlobData> blobData = BlobData::create();
90     blobData->appendArrayBufferView(body->view());
91     const long long length = blobData->length();
92     Blob* blob = Blob::create(BlobDataHandle::create(blobData.release(), length));
93     return create(context, blob, ResponseInit(responseInit, exceptionState), exceptionState);
94 }
95
96 Response* Response::create(ExecutionContext* context, Blob* body, const ResponseInit& responseInit, ExceptionState& exceptionState)
97 {
98     // "1. If |init|'s status member is not in the range 200 to 599, throw a
99     // RangeError."
100     if (responseInit.status < 200 || 599 < responseInit.status) {
101         exceptionState.throwRangeError("Invalid status");
102         return 0;
103     }
104
105     // FIXME: "2. If |init|'s statusText member does not match the Reason-Phrase
106     //        token production, throw a TypeError."
107
108     // "3. Let |r| be a new Response object, associated with a new response,
109     // Headers object, and Body object."
110     Response* r = new Response(context);
111     r->suspendIfNeeded();
112
113     // "4. Set |r|'s response's status to |init|'s status member."
114     r->m_response->setStatus(responseInit.status);
115
116     // "5. Set |r|'s response's status message to |init|'s statusText member."
117     r->m_response->setStatusMessage(AtomicString(responseInit.statusText));
118
119     // "6. If |init|'s headers member is present, run these substeps:"
120     if (responseInit.headers) {
121         // "1. Empty |r|'s response's header list."
122         r->m_response->headerList()->clearList();
123         // "2. Fill |r|'s Headers object with |init|'s headers member. Rethrow
124         // any exceptions."
125         r->m_headers->fillWith(responseInit.headers.get(), exceptionState);
126         if (exceptionState.hadException())
127             return 0;
128     } else if (!responseInit.headersDictionary.isUndefinedOrNull()) {
129         // "1. Empty |r|'s response's header list."
130         r->m_response->headerList()->clearList();
131         // "2. Fill |r|'s Headers object with |init|'s headers member. Rethrow
132         // any exceptions."
133         r->m_headers->fillWith(responseInit.headersDictionary, exceptionState);
134         if (exceptionState.hadException())
135             return 0;
136     }
137     // "7. If body is given, run these substeps:"
138     if (body) {
139         // "1. Let |stream| and |Content-Type| be the result of extracting body."
140         // "2. Set |r|'s response's body to |stream|."
141         // "3. If |Content-Type| is non-null and |r|'s response's header list
142         // contains no header named `Content-Type`, append `Content-Type`/
143         // |Content-Type| to |r|'s response's header list."
144         r->m_response->setBlobDataHandle(body->blobDataHandle());
145         if (!body->type().isNull() && !r->m_response->headerList()->has("Content-Type"))
146             r->m_response->headerList()->append("Content-Type", body->type());
147     }
148
149     // FIXME: "8. Set |r|'s MIME type to the result of extracting a MIME type
150     //        from |r|'s response's header list."
151
152     // "9. Return |r|."
153     return r;
154 }
155
156 Response* Response::create(ExecutionContext* context, FetchResponseData* response)
157 {
158     Response* r = new Response(context, response);
159     r->suspendIfNeeded();
160     return r;
161 }
162
163 Response* Response::create(ExecutionContext* context, const WebServiceWorkerResponse& webResponse)
164 {
165     FetchResponseData* responseData = createFetchResponseDataFromWebResponse(webResponse);
166     Response* r = new Response(context, responseData);
167     r->suspendIfNeeded();
168     return r;
169 }
170
171 Response* Response::create(const Response& copyFrom)
172 {
173     Response* r = new Response(copyFrom);
174     r->suspendIfNeeded();
175     return r;
176 }
177
178 String Response::type() const
179 {
180     // "The type attribute's getter must return response's type."
181     switch (m_response->type()) {
182     case FetchResponseData::BasicType:
183         return "basic";
184     case FetchResponseData::CORSType:
185         return "cors";
186     case FetchResponseData::DefaultType:
187         return "default";
188     case FetchResponseData::ErrorType:
189         return "error";
190     case FetchResponseData::OpaqueType:
191         return "opaque";
192     }
193     ASSERT_NOT_REACHED();
194     return "";
195 }
196
197 String Response::url() const
198 {
199     // "The url attribute's getter must return the empty string if response's
200     // url is null and response's url, serialized with the exclude fragment
201     // flag set, otherwise."
202     if (!m_response->url().hasFragmentIdentifier())
203         return m_response->url();
204     KURL url(m_response->url());
205     url.removeFragmentIdentifier();
206     return url;
207 }
208
209 unsigned short Response::status() const
210 {
211     // "The status attribute's getter must return response's status."
212     return m_response->status();
213 }
214
215 String Response::statusText() const
216 {
217     // "The statusText attribute's getter must return response's status message."
218     return m_response->statusMessage();
219 }
220
221 Headers* Response::headers() const
222 {
223     // "The headers attribute's getter must return the associated Headers object."
224     return m_headers;
225 }
226
227 Response* Response::clone() const
228 {
229     return Response::create(*this);
230 }
231
232 void Response::populateWebServiceWorkerResponse(WebServiceWorkerResponse& response)
233 {
234     m_response->populateWebServiceWorkerResponse(response);
235 }
236
237 Response::Response(ExecutionContext* context)
238     : Body(context)
239     , m_response(FetchResponseData::create())
240     , m_headers(Headers::create(m_response->headerList()))
241 {
242     m_headers->setGuard(Headers::ResponseGuard);
243 }
244
245 Response::Response(const Response& copy_from)
246     : Body(copy_from)
247     , m_response(copy_from.m_response)
248     , m_headers(copy_from.m_headers->createCopy())
249 {
250 }
251
252 Response::Response(ExecutionContext* context, FetchResponseData* response)
253     : Body(context)
254     , m_response(response)
255     , m_headers(Headers::create(m_response->headerList()))
256 {
257     m_headers->setGuard(Headers::ResponseGuard);
258 }
259
260
261 PassRefPtr<BlobDataHandle> Response::blobDataHandle()
262 {
263     return m_response->blobDataHandle();
264 }
265
266 void Response::trace(Visitor* visitor)
267 {
268     Body::trace(visitor);
269     visitor->trace(m_response);
270     visitor->trace(m_headers);
271 }
272
273 } // namespace blink