86e94365410f71c0da8912c01a52466d4d87acac
[WebKit-https.git] / WebCore / bindings / js / JSXMLHttpRequestCustom.cpp
1 /*
2  * Copyright (C) 2008 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 "DOMWindow.h"
33 #include "Document.h"
34 #include "Event.h"
35 #include "File.h"
36 #include "Frame.h"
37 #include "FrameLoader.h"
38 #include "HTMLDocument.h"
39 #include "JSDOMWindowCustom.h"
40 #include "JSDocument.h"
41 #include "JSEvent.h"
42 #include "JSEventListener.h"
43 #include "JSFile.h"
44 #include "XMLHttpRequest.h"
45 #include <runtime/Error.h>
46 #include <interpreter/Interpreter.h>
47
48 using namespace JSC;
49
50 namespace WebCore {
51
52 void JSXMLHttpRequest::mark()
53 {
54     Base::mark();
55
56     if (XMLHttpRequestUpload* upload = m_impl->optionalUpload()) {
57         DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), upload);
58         if (wrapper && !wrapper->marked())
59             wrapper->mark();
60     }
61
62     if (JSEventListener* onReadyStateChangeListener = static_cast<JSEventListener*>(m_impl->onreadystatechange()))
63         onReadyStateChangeListener->mark();
64
65     if (JSEventListener* onAbortListener = static_cast<JSEventListener*>(m_impl->onabort()))
66         onAbortListener->mark();
67
68     if (JSEventListener* onErrorListener = static_cast<JSEventListener*>(m_impl->onerror()))
69         onErrorListener->mark();
70
71     if (JSEventListener* onLoadListener = static_cast<JSEventListener*>(m_impl->onload()))
72         onLoadListener->mark();
73
74     if (JSEventListener* onLoadStartListener = static_cast<JSEventListener*>(m_impl->onloadstart()))
75         onLoadStartListener->mark();
76     
77     if (JSEventListener* onProgressListener = static_cast<JSEventListener*>(m_impl->onprogress()))
78         onProgressListener->mark();
79     
80     typedef XMLHttpRequest::EventListenersMap EventListenersMap;
81     typedef XMLHttpRequest::ListenerVector ListenerVector;
82     EventListenersMap& eventListeners = m_impl->eventListeners();
83     for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
84         for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter) {
85             JSEventListener* listener = static_cast<JSEventListener*>(vecIter->get());
86             listener->mark();
87         }
88     }
89 }
90
91 // Custom functions
92 JSValuePtr JSXMLHttpRequest::open(ExecState* exec, const ArgList& args)
93 {
94     if (args.size() < 2)
95         return throwError(exec, SyntaxError, "Not enough arguments");
96
97     const KURL& url = impl()->scriptExecutionContext()->completeURL(args.at(exec, 1).toString(exec));
98     String method = args.at(exec, 0).toString(exec);
99     bool async = true;
100     if (args.size() >= 3)
101         async = args.at(exec, 2).toBoolean(exec);
102
103     ExceptionCode ec = 0;
104     if (args.size() >= 4 && !args.at(exec, 3).isUndefined()) {
105         String user = valueToStringWithNullCheck(exec, args.at(exec, 3));
106
107         if (args.size() >= 5 && !args.at(exec, 4).isUndefined()) {
108             String password = valueToStringWithNullCheck(exec, args.at(exec, 4));
109             impl()->open(method, url, async, user, password, ec);
110         } else
111             impl()->open(method, url, async, user, ec);
112     } else
113         impl()->open(method, url, async, ec);
114
115     setDOMException(exec, ec);
116     return jsUndefined();
117 }
118
119 JSValuePtr JSXMLHttpRequest::setRequestHeader(ExecState* exec, const ArgList& args)
120 {
121     if (args.size() < 2)
122         return throwError(exec, SyntaxError, "Not enough arguments");
123
124     ExceptionCode ec = 0;
125     impl()->setRequestHeader(args.at(exec, 0).toString(exec), args.at(exec, 1).toString(exec), ec);
126     setDOMException(exec, ec);
127     return jsUndefined();
128 }
129
130 JSValuePtr JSXMLHttpRequest::send(ExecState* exec, const ArgList& args)
131 {
132     ExceptionCode ec = 0;
133     if (args.isEmpty())
134         impl()->send(ec);
135     else {
136         JSValuePtr val = args.at(exec, 0);
137         if (val.isUndefinedOrNull())
138             impl()->send(ec);
139         else if (val.isObject(&JSDocument::s_info))
140             impl()->send(toDocument(val), ec);
141         else if (val.isObject(&JSFile::s_info))
142             impl()->send(toFile(val), ec);
143         else
144             impl()->send(val.toString(exec), ec);
145     }
146
147     int signedLineNumber;
148     intptr_t sourceID;
149     UString sourceURL;
150     JSValuePtr function;
151     exec->interpreter()->retrieveLastCaller(exec, signedLineNumber, sourceID, sourceURL, function);
152     impl()->setLastSendLineNumber(signedLineNumber >= 0 ? signedLineNumber : 0);
153     impl()->setLastSendURL(sourceURL);
154
155     setDOMException(exec, ec);
156     return jsUndefined();
157 }
158
159 JSValuePtr JSXMLHttpRequest::getResponseHeader(ExecState* exec, const ArgList& args)
160 {
161     if (args.size() < 1)
162         return throwError(exec, SyntaxError, "Not enough arguments");
163
164     ExceptionCode ec = 0;
165     JSValuePtr header = jsStringOrNull(exec, impl()->getResponseHeader(args.at(exec, 0).toString(exec), ec));
166     setDOMException(exec, ec);
167     return header;
168 }
169
170 JSValuePtr JSXMLHttpRequest::overrideMimeType(ExecState* exec, const ArgList& args)
171 {
172     if (args.size() < 1)
173         return throwError(exec, SyntaxError, "Not enough arguments");
174
175     impl()->overrideMimeType(args.at(exec, 0).toString(exec));
176     return jsUndefined();
177 }
178
179 JSValuePtr JSXMLHttpRequest::addEventListener(ExecState* exec, const ArgList& args)
180 {
181     JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
182     if (!globalObject)
183         return jsUndefined();
184     RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(exec, args.at(exec, 1));
185     if (!listener)
186         return jsUndefined();
187     impl()->addEventListener(args.at(exec, 0).toString(exec), listener.release(), args.at(exec, 2).toBoolean(exec));
188     return jsUndefined();
189 }
190
191 JSValuePtr JSXMLHttpRequest::removeEventListener(ExecState* exec, const ArgList& args)
192 {
193     JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
194     if (!globalObject)
195         return jsUndefined();
196     JSEventListener* listener = globalObject->findJSEventListener(exec, args.at(exec, 1));
197     if (!listener)
198         return jsUndefined();
199     impl()->removeEventListener(args.at(exec, 0).toString(exec), listener, args.at(exec, 2).toBoolean(exec));
200     return jsUndefined();
201 }
202
203 JSValuePtr JSXMLHttpRequest::responseText(ExecState* exec) const
204 {
205     return jsOwnedStringOrNull(exec, impl()->responseText());
206 }
207
208 } // namespace WebCore