1/*
2 * Copyright (C) 2008, 2009 Apple 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
6 * are met:
7 *
8 * 1.  Redistributions of source code must retain the above copyright
9 *     notice, this list of conditions and the following disclaimer.
10 * 2.  Redistributions in binary form must reproduce the above copyright
11 *     notice, this list of conditions and the following disclaimer in the
12 *     documentation and/or other materials provided with the distribution.
13 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 *     its contributors may be used to endorse or promote products derived
15 *     from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "config.h"
30#include "JSXMLHttpRequest.h"
31
32#include "ArrayBuffer.h"
33#include "Blob.h"
34#include "DOMFormData.h"
35#include "DOMWindow.h"
36#include "Document.h"
37#include "Event.h"
38#include "Frame.h"
39#include "FrameLoader.h"
40#include "HTMLDocument.h"
41#include "InspectorInstrumentation.h"
42#include "JSArrayBuffer.h"
43#include "JSBlob.h"
44#include "JSDOMFormData.h"
45#include "JSDOMWindowCustom.h"
46#include "JSDocument.h"
47#include "JSEvent.h"
48#include "JSEventListener.h"
49#include "XMLHttpRequest.h"
50#include <runtime/Error.h>
51#include <interpreter/Interpreter.h>
52
53using namespace JSC;
54
55namespace WebCore {
56
57void JSXMLHttpRequest::markChildren(MarkStack& markStack)
58{
59    Base::markChildren(markStack);
60
61    if (XMLHttpRequestUpload* upload = m_impl->optionalUpload())
62        markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), upload);
63
64    if (Document* responseDocument = m_impl->optionalResponseXML())
65        markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), responseDocument);
66
67    if (ArrayBuffer* responseArrayBuffer = m_impl->optionalResponseArrayBuffer())
68        markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), responseArrayBuffer);
69
70#if ENABLE(XHR_RESPONSE_BLOB)
71    if (Blob* responseBlob = m_impl->optionalResponseBlob())
72        markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), responseBlob);
73#endif
74
75    m_impl->markJSEventListeners(markStack);
76}
77
78// Custom functions
79JSValue JSXMLHttpRequest::open(ExecState* exec)
80{
81    if (exec->argumentCount() < 2)
82        return throwError(exec, createSyntaxError(exec, "Not enough arguments"));
83
84    const KURL& url = impl()->scriptExecutionContext()->completeURL(ustringToString(exec->argument(1).toString(exec)));
85    String method = ustringToString(exec->argument(0).toString(exec));
86
87    ExceptionCode ec = 0;
88    if (exec->argumentCount() >= 3) {
89        bool async = exec->argument(2).toBoolean(exec);
90
91        if (exec->argumentCount() >= 4 && !exec->argument(3).isUndefined()) {
92            String user = valueToStringWithNullCheck(exec, exec->argument(3));
93
94            if (exec->argumentCount() >= 5 && !exec->argument(4).isUndefined()) {
95                String password = valueToStringWithNullCheck(exec, exec->argument(4));
96                impl()->open(method, url, async, user, password, ec);
97            } else
98                impl()->open(method, url, async, user, ec);
99        } else
100            impl()->open(method, url, async, ec);
101    } else
102        impl()->open(method, url, ec);
103
104    setDOMException(exec, ec);
105    return jsUndefined();
106}
107
108JSValue JSXMLHttpRequest::send(ExecState* exec)
109{
110    InspectorInstrumentation::willSendXMLHttpRequest(impl()->scriptExecutionContext(), impl()->url());
111
112    ExceptionCode ec = 0;
113    if (!exec->argumentCount())
114        impl()->send(ec);
115    else {
116        JSValue val = exec->argument(0);
117        if (val.isUndefinedOrNull())
118            impl()->send(ec);
119        else if (val.inherits(&JSDocument::s_info))
120            impl()->send(toDocument(val), ec);
121        else if (val.inherits(&JSBlob::s_info))
122            impl()->send(toBlob(val), ec);
123        else if (val.inherits(&JSDOMFormData::s_info))
124            impl()->send(toDOMFormData(val), ec);
125        else if (val.inherits(&JSArrayBuffer::s_info))
126            impl()->send(toArrayBuffer(val), ec);
127        else
128            impl()->send(ustringToString(val.toString(exec)), ec);
129    }
130
131    int signedLineNumber;
132    intptr_t sourceID;
133    UString sourceURL;
134    JSValue function;
135    exec->interpreter()->retrieveLastCaller(exec, signedLineNumber, sourceID, sourceURL, function);
136    impl()->setLastSendLineNumber(signedLineNumber >= 0 ? signedLineNumber : 0);
137    impl()->setLastSendURL(ustringToString(sourceURL));
138
139    setDOMException(exec, ec);
140    return jsUndefined();
141}
142
143JSValue JSXMLHttpRequest::responseText(ExecState* exec) const
144{
145    ExceptionCode ec = 0;
146    String text = impl()->responseText(ec);
147    if (ec) {
148        setDOMException(exec, ec);
149        return jsUndefined();
150    }
151    return jsOwnedStringOrNull(exec, text);
152}
153
154JSValue JSXMLHttpRequest::response(ExecState* exec) const
155{
156    switch (impl()->responseTypeCode()) {
157    case XMLHttpRequest::ResponseTypeDefault:
158    case XMLHttpRequest::ResponseTypeText:
159        return responseText(exec);
160
161    case XMLHttpRequest::ResponseTypeDocument:
162        {
163            ExceptionCode ec = 0;
164            Document* document = impl()->responseXML(ec);
165            if (ec) {
166                setDOMException(exec, ec);
167                return jsUndefined();
168            }
169            return toJS(exec, globalObject(), document);
170        }
171
172    case XMLHttpRequest::ResponseTypeBlob:
173#if ENABLE(XHR_RESPONSE_BLOB)
174        {
175            ExceptionCode ec = 0;
176            Blob* blob = impl()->responseBlob(ec);
177            if (ec) {
178                setDOMException(exec, ec);
179                return jsUndefined();
180            }
181            return toJS(exec, globalObject(), blob);
182        }
183#else
184        return jsUndefined();
185#endif
186
187    case XMLHttpRequest::ResponseTypeArrayBuffer:
188        {
189            ExceptionCode ec = 0;
190            ArrayBuffer* arrayBuffer = impl()->responseArrayBuffer(ec);
191            if (ec) {
192                setDOMException(exec, ec);
193                return jsUndefined();
194            }
195            return toJS(exec, globalObject(), arrayBuffer);
196        }
197    }
198
199    return jsUndefined();
200}
201
202EncodedJSValue JSC_HOST_CALL JSXMLHttpRequestConstructor::constructJSXMLHttpRequest(ExecState* exec)
203{
204    JSXMLHttpRequestConstructor* jsConstructor = static_cast<JSXMLHttpRequestConstructor*>(exec->callee());
205    ScriptExecutionContext* context = jsConstructor->scriptExecutionContext();
206    if (!context)
207        return throwVMError(exec, createReferenceError(exec, "XMLHttpRequest constructor associated document is unavailable"));
208
209    RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context);
210    return JSValue::encode(CREATE_DOM_OBJECT_WRAPPER(exec, jsConstructor->globalObject(), XMLHttpRequest, xmlHttpRequest.get()));
211}
212
213} // namespace WebCore
214