Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / core / v8 / custom / V8XMLHttpRequestCustom.cpp
1 /*
2  * Copyright (C) 2008, 2009, 2010 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "bindings/core/v8/V8XMLHttpRequest.h"
33
34 #include "bindings/core/v8/ExceptionMessages.h"
35 #include "bindings/core/v8/ExceptionState.h"
36 #include "bindings/core/v8/V8Binding.h"
37 #include "bindings/core/v8/V8Blob.h"
38 #include "bindings/core/v8/V8Document.h"
39 #include "bindings/core/v8/V8FormData.h"
40 #include "bindings/core/v8/V8HTMLDocument.h"
41 #include "bindings/core/v8/V8ReadableStream.h"
42 #include "bindings/core/v8/V8Stream.h"
43 #include "bindings/core/v8/custom/V8ArrayBufferCustom.h"
44 #include "bindings/core/v8/custom/V8ArrayBufferViewCustom.h"
45 #include "core/dom/Document.h"
46 #include "core/inspector/InspectorInstrumentation.h"
47 #include "core/streams/ReadableStream.h"
48 #include "core/streams/Stream.h"
49 #include "core/workers/WorkerGlobalScope.h"
50 #include "core/xml/XMLHttpRequest.h"
51 #include "wtf/ArrayBuffer.h"
52 #include <v8.h>
53
54 namespace blink {
55
56 void V8XMLHttpRequest::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
57 {
58     ExecutionContext* context = currentExecutionContext(info.GetIsolate());
59
60     RefPtr<SecurityOrigin> securityOrigin;
61     if (context->isDocument()) {
62         DOMWrapperWorld& world = DOMWrapperWorld::current(info.GetIsolate());
63         if (world.isIsolatedWorld())
64             securityOrigin = world.isolatedWorldSecurityOrigin();
65     }
66
67     RefPtrWillBeRawPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context, securityOrigin);
68
69     v8::Handle<v8::Object> wrapper = info.Holder();
70     V8DOMWrapper::associateObjectWithWrapper<V8XMLHttpRequest>(xmlHttpRequest.release(), &wrapperTypeInfo, wrapper, info.GetIsolate());
71     info.GetReturnValue().Set(wrapper);
72 }
73
74 void V8XMLHttpRequest::responseTextAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info)
75 {
76     XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toImpl(info.Holder());
77     ExceptionState exceptionState(ExceptionState::GetterContext, "responseText", "XMLHttpRequest", info.Holder(), info.GetIsolate());
78     ScriptString text = xmlHttpRequest->responseText(exceptionState);
79     if (exceptionState.throwIfNeeded())
80         return;
81     if (text.isEmpty()) {
82         v8SetReturnValueString(info, emptyString(), info.GetIsolate());
83         return;
84     }
85     v8SetReturnValue(info, text.v8Value());
86 }
87
88 void V8XMLHttpRequest::responseAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info)
89 {
90     XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toImpl(info.Holder());
91
92     switch (xmlHttpRequest->responseTypeCode()) {
93     case XMLHttpRequest::ResponseTypeDefault:
94     case XMLHttpRequest::ResponseTypeText:
95         responseTextAttributeGetterCustom(info);
96         return;
97
98     case XMLHttpRequest::ResponseTypeJSON:
99         {
100             v8::Isolate* isolate = info.GetIsolate();
101
102             ScriptString jsonSource = xmlHttpRequest->responseJSONSource();
103             if (jsonSource.isEmpty()) {
104                 v8SetReturnValue(info, v8::Null(isolate));
105                 return;
106             }
107
108             // Catch syntax error.
109             v8::TryCatch exceptionCatcher;
110             v8::Handle<v8::Value> json = v8::JSON::Parse(jsonSource.v8Value());
111             if (exceptionCatcher.HasCaught() || json.IsEmpty())
112                 v8SetReturnValue(info, v8::Null(isolate));
113             else
114                 v8SetReturnValue(info, json);
115             return;
116         }
117
118     case XMLHttpRequest::ResponseTypeDocument:
119         {
120             ExceptionState exceptionState(ExceptionState::GetterContext, "response", "XMLHttpRequest", info.Holder(), info.GetIsolate());
121             Document* document = xmlHttpRequest->responseXML(exceptionState);
122             if (exceptionState.throwIfNeeded())
123                 return;
124             v8SetReturnValueFast(info, document, xmlHttpRequest);
125             return;
126         }
127
128     case XMLHttpRequest::ResponseTypeBlob:
129         {
130             Blob* blob = xmlHttpRequest->responseBlob();
131             v8SetReturnValueFast(info, blob, xmlHttpRequest);
132             return;
133         }
134
135     case XMLHttpRequest::ResponseTypeLegacyStream:
136         {
137             Stream* stream = xmlHttpRequest->responseLegacyStream();
138             v8SetReturnValueFast(info, stream, xmlHttpRequest);
139             return;
140         }
141
142     case XMLHttpRequest::ResponseTypeStream:
143         {
144             ReadableStream* stream = xmlHttpRequest->responseStream();
145             v8SetReturnValueFast(info, stream, xmlHttpRequest);
146             return;
147         }
148
149     case XMLHttpRequest::ResponseTypeArrayBuffer:
150         {
151             ArrayBuffer* arrayBuffer = xmlHttpRequest->responseArrayBuffer();
152             if (arrayBuffer) {
153                 arrayBuffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate());
154             }
155             v8SetReturnValueFast(info, arrayBuffer, xmlHttpRequest);
156             return;
157         }
158     }
159 }
160
161 void V8XMLHttpRequest::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
162 {
163     // Four cases:
164     // open(method, url)
165     // open(method, url, async)
166     // open(method, url, async, user)
167     // open(method, url, async, user, passwd)
168
169     ExceptionState exceptionState(ExceptionState::ExecutionContext, "open", "XMLHttpRequest", info.Holder(), info.GetIsolate());
170
171     if (info.Length() < 2) {
172         exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(2, info.Length()));
173         exceptionState.throwIfNeeded();
174         return;
175     }
176
177     XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toImpl(info.Holder());
178
179     TOSTRING_VOID(V8StringResource<>, method, info[0]);
180     TOSTRING_VOID(V8StringResource<>, urlstring, info[1]);
181
182     ExecutionContext* context = currentExecutionContext(info.GetIsolate());
183     KURL url = context->completeURL(urlstring);
184
185     if (info.Length() >= 3) {
186         bool async = info[2]->BooleanValue();
187
188         if (info.Length() >= 4 && !info[3]->IsUndefined()) {
189             TOSTRING_VOID(V8StringResource<TreatNullAsNullString>, user, info[3]);
190
191             if (info.Length() >= 5 && !info[4]->IsUndefined()) {
192                 TOSTRING_VOID(V8StringResource<TreatNullAsNullString>, password, info[4]);
193                 xmlHttpRequest->open(method, url, async, user, password, exceptionState);
194             } else {
195                 xmlHttpRequest->open(method, url, async, user, exceptionState);
196             }
197         } else {
198             xmlHttpRequest->open(method, url, async, exceptionState);
199         }
200     } else {
201         xmlHttpRequest->open(method, url, exceptionState);
202     }
203
204     exceptionState.throwIfNeeded();
205 }
206
207 static bool isDocumentType(v8::Handle<v8::Value> value, v8::Isolate* isolate)
208 {
209     // FIXME: add other document types.
210     return V8Document::hasInstance(value, isolate) || V8HTMLDocument::hasInstance(value, isolate);
211 }
212
213 void V8XMLHttpRequest::sendMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
214 {
215     XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toImpl(info.Holder());
216
217     InspectorInstrumentation::willSendXMLHttpRequest(xmlHttpRequest->executionContext(), xmlHttpRequest->url());
218
219     ExceptionState exceptionState(ExceptionState::ExecutionContext, "send", "XMLHttpRequest", info.Holder(), info.GetIsolate());
220     if (info.Length() < 1) {
221         xmlHttpRequest->send(exceptionState);
222     } else {
223         v8::Handle<v8::Value> arg = info[0];
224         if (isUndefinedOrNull(arg)) {
225             xmlHttpRequest->send(exceptionState);
226         } else if (isDocumentType(arg, info.GetIsolate())) {
227             v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg);
228             Document* document = V8Document::toImpl(object);
229             ASSERT(document);
230             xmlHttpRequest->send(document, exceptionState);
231         } else if (V8Blob::hasInstance(arg, info.GetIsolate())) {
232             v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg);
233             Blob* blob = V8Blob::toImpl(object);
234             ASSERT(blob);
235             xmlHttpRequest->send(blob, exceptionState);
236         } else if (V8FormData::hasInstance(arg, info.GetIsolate())) {
237             v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg);
238             DOMFormData* domFormData = V8FormData::toImpl(object);
239             ASSERT(domFormData);
240             xmlHttpRequest->send(domFormData, exceptionState);
241         } else if (V8ArrayBuffer::hasInstance(arg, info.GetIsolate())) {
242             v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg);
243             ArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(object);
244             ASSERT(arrayBuffer);
245             xmlHttpRequest->send(arrayBuffer, exceptionState);
246         } else if (V8ArrayBufferView::hasInstance(arg, info.GetIsolate())) {
247             v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg);
248             ArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object);
249             ASSERT(arrayBufferView);
250             xmlHttpRequest->send(arrayBufferView, exceptionState);
251         } else {
252             TOSTRING_VOID(V8StringResource<TreatNullAsNullString>, argString, arg);
253             xmlHttpRequest->send(argString, exceptionState);
254         }
255     }
256
257     exceptionState.throwIfNeeded();
258 }
259
260 } // namespace blink