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 53 using namespace JSC; 54 55 namespace WebCore { 56 57 void 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 79 JSValue 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 108 JSValue 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 143 JSValue 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 154 JSValue 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 202 EncodedJSValue 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