webengine/osswebengine/WebCore/bindings/js/JSXMLHttpRequest.cpp
changeset 0 dd21522fd290
child 68 92a765b5b3e7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebCore/bindings/js/JSXMLHttpRequest.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,331 @@
+/*
+ *  This file is part of the KDE libraries
+ *  Copyright (C) 2004, 2007 Apple Inc. All rights reserved.
+ *  Copyright (C) 2005, 2006 Alexey Proskuryakov <ap@nypop.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "JSXMLHttpRequest.h"
+
+#include "DOMWindow.h"
+#include "Event.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "HTMLDocument.h"
+#include "JSDocument.h"
+#include "JSEvent.h"
+#include "XMLHttpRequest.h"
+#include "kjs_events.h"
+#include "kjs_window.h"
+
+#include "JSXMLHttpRequest.lut.h"
+
+namespace KJS {
+
+using namespace WebCore;
+
+////////////////////// JSXMLHttpRequest Object ////////////////////////
+
+/* Source for JSXMLHttpRequestPrototypeTable.
+@begin JSXMLHttpRequestPrototypeTable 7
+  abort                 JSXMLHttpRequest::Abort                   DontDelete|Function 0
+  getAllResponseHeaders JSXMLHttpRequest::GetAllResponseHeaders   DontDelete|Function 0
+  getResponseHeader     JSXMLHttpRequest::GetResponseHeader       DontDelete|Function 1
+  open                  JSXMLHttpRequest::Open                    DontDelete|Function 5
+  overrideMimeType      JSXMLHttpRequest::OverrideMIMEType        DontDelete|Function 1
+  send                  JSXMLHttpRequest::Send                    DontDelete|Function 1
+  setRequestHeader      JSXMLHttpRequest::SetRequestHeader        DontDelete|Function 2
+# from the EventTarget interface
+# FIXME: add DOM3 EventTarget methods (addEventListenerNS, removeEventListenerNS).
+  addEventListener      JSXMLHttpRequest::AddEventListener        DontDelete|Function 3
+  removeEventListener   JSXMLHttpRequest::RemoveEventListener     DontDelete|Function 3
+  dispatchEvent         JSXMLHttpRequest::DispatchEvent           DontDelete|Function 1
+@end
+*/
+KJS_DEFINE_PROTOTYPE(JSXMLHttpRequestPrototype)
+KJS_IMPLEMENT_PROTOTYPE_FUNCTION(JSXMLHttpRequestPrototypeFunction)
+KJS_IMPLEMENT_PROTOTYPE("JSXMLHttpRequest", JSXMLHttpRequestPrototype, JSXMLHttpRequestPrototypeFunction)
+
+JSXMLHttpRequestConstructorImp::JSXMLHttpRequestConstructorImp(ExecState* exec, Document* d)
+    : doc(d)
+{
+    setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
+    putDirect(exec->propertyNames().prototype, JSXMLHttpRequestPrototype::self(exec), None);
+}
+
+bool JSXMLHttpRequestConstructorImp::implementsConstruct() const
+{
+    return true;
+}
+
+JSObject* JSXMLHttpRequestConstructorImp::construct(ExecState* exec, const List&)
+{
+    return new JSXMLHttpRequest(exec, doc.get());
+}
+
+const ClassInfo JSXMLHttpRequest::info = { "JSXMLHttpRequest", 0, &JSXMLHttpRequestTable, 0 };
+
+/* Source for JSXMLHttpRequestTable.
+@begin JSXMLHttpRequestTable 7
+  readyState            JSXMLHttpRequest::ReadyState              DontDelete|ReadOnly
+  responseText          JSXMLHttpRequest::ResponseText            DontDelete|ReadOnly
+  responseXML           JSXMLHttpRequest::ResponseXML             DontDelete|ReadOnly
+  status                JSXMLHttpRequest::Status                  DontDelete|ReadOnly
+  statusText            JSXMLHttpRequest::StatusText              DontDelete|ReadOnly
+  onreadystatechange    JSXMLHttpRequest::Onreadystatechange      DontDelete
+  onload                JSXMLHttpRequest::Onload                  DontDelete
+@end
+*/
+
+bool JSXMLHttpRequest::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+    return getStaticValueSlot<JSXMLHttpRequest, DOMObject>(exec, &JSXMLHttpRequestTable, this, propertyName, slot);
+}
+
+JSValue* JSXMLHttpRequest::getValueProperty(ExecState* exec, int token) const
+{
+    ExceptionCode ec = 0;
+
+    switch (token) {
+        case ReadyState:
+            return jsNumber(m_impl->getReadyState());
+        case ResponseText:
+            return jsOwnedStringOrNull(m_impl->getResponseText());
+        case ResponseXML:
+            if (Document* responseXML = m_impl->getResponseXML())
+                return toJS(exec, responseXML);
+            return jsNull();
+        case Status: {
+            JSValue* result = jsNumber(m_impl->getStatus(ec));
+            setDOMException(exec, ec);
+            return result;
+        }
+        case StatusText: {
+            JSValue* result = jsString(m_impl->getStatusText(ec));
+            setDOMException(exec, ec);
+            return result;
+        }
+        case Onreadystatechange:
+            if (JSUnprotectedEventListener* listener = static_cast<JSUnprotectedEventListener*>(m_impl->onReadyStateChangeListener()))
+                if (JSObject* listenerObj = listener->listenerObj())
+                    return listenerObj;
+            return jsNull();
+        case Onload:
+            if (JSUnprotectedEventListener* listener = static_cast<JSUnprotectedEventListener*>(m_impl->onLoadListener()))
+                if (JSObject* listenerObj = listener->listenerObj())
+                    return listenerObj;
+            return jsNull();
+        default:
+            return 0;
+    }
+}
+
+void JSXMLHttpRequest::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)
+{
+    lookupPut<JSXMLHttpRequest,DOMObject>(exec, propertyName, value, attr, &JSXMLHttpRequestTable, this );
+}
+
+void JSXMLHttpRequest::putValueProperty(ExecState* exec, int token, JSValue* value, int /*attr*/)
+{
+    switch (token) {
+        case Onreadystatechange: {
+            Document* doc = m_impl->document();
+            if (!doc)
+                return;
+            Frame* frame = doc->frame();
+            if (!frame)
+                return;
+            m_impl->setOnReadyStateChangeListener(KJS::Window::retrieveWindow(frame)->findOrCreateJSUnprotectedEventListener(value, true));
+            break;
+        }
+        case Onload: {
+            Document* doc = m_impl->document();
+            if (!doc)
+                return;
+            Frame* frame = doc->frame();
+            if (!frame)
+                return;
+            m_impl->setOnLoadListener(KJS::Window::retrieveWindow(frame)->findOrCreateJSUnprotectedEventListener(value, true));
+            break;
+        }
+    }
+}
+
+void JSXMLHttpRequest::mark()
+{
+    DOMObject::mark();
+
+    JSUnprotectedEventListener* onReadyStateChangeListener = static_cast<JSUnprotectedEventListener*>(m_impl->onReadyStateChangeListener());
+    JSUnprotectedEventListener* onLoadListener = static_cast<JSUnprotectedEventListener*>(m_impl->onLoadListener());
+
+    if (onReadyStateChangeListener)
+        onReadyStateChangeListener->mark();
+
+    if (onLoadListener)
+        onLoadListener->mark();
+    
+    typedef XMLHttpRequest::EventListenersMap EventListenersMap;
+    typedef XMLHttpRequest::ListenerVector ListenerVector;
+    EventListenersMap& eventListeners = m_impl->eventListeners();
+    for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
+        for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter) {
+            JSUnprotectedEventListener* listener = static_cast<JSUnprotectedEventListener*>(vecIter->get());
+            listener->mark();
+        }
+    }
+}
+
+
+JSXMLHttpRequest::JSXMLHttpRequest(ExecState* exec, Document* d)
+  : m_impl(new XMLHttpRequest(d))
+{
+    setPrototype(JSXMLHttpRequestPrototype::self(exec));
+    ScriptInterpreter::putDOMObject(m_impl.get(), this);
+}
+
+JSXMLHttpRequest::~JSXMLHttpRequest()
+{
+    m_impl->setOnReadyStateChangeListener(0);
+    m_impl->setOnLoadListener(0);
+    m_impl->eventListeners().clear();
+    ScriptInterpreter::forgetDOMObject(m_impl.get());
+}
+
+JSValue* JSXMLHttpRequestPrototypeFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
+{
+    if (!thisObj->inherits(&JSXMLHttpRequest::info))
+        return throwError(exec, TypeError);
+
+    JSXMLHttpRequest* request = static_cast<JSXMLHttpRequest*>(thisObj);
+
+    ExceptionCode ec = 0;
+
+    switch (id) {
+        case JSXMLHttpRequest::Abort:
+            request->m_impl->abort();
+            return jsUndefined();
+
+        case JSXMLHttpRequest::GetAllResponseHeaders:
+            return jsStringOrUndefined(request->m_impl->getAllResponseHeaders());
+
+        case JSXMLHttpRequest::GetResponseHeader:
+            if (args.size() < 1)
+                return throwError(exec, SyntaxError, "Not enough arguments");
+
+            return jsStringOrNull(request->m_impl->getResponseHeader(args[0]->toString(exec)));
+
+        case JSXMLHttpRequest::Open: {
+            if (args.size() < 2)
+                return throwError(exec, SyntaxError, "Not enough arguments");
+
+            String method = args[0]->toString(exec);
+            Frame* frame = Window::retrieveActive(exec)->impl()->frame();
+            if (!frame)
+                return jsUndefined();
+            KURL url = frame->loader()->completeURL(DeprecatedString(args[1]->toString(exec)));
+
+            bool async = true;
+            if (args.size() >= 3)
+                async = args[2]->toBoolean(exec);
+
+            if (args.size() >= 4 && !args[3]->isUndefined()) {
+                String user = valueToStringWithNullCheck(exec, args[3]);
+
+                if (args.size() >= 5 && !args[4]->isUndefined()) {
+                    String password = valueToStringWithNullCheck(exec, args[4]);
+                    request->m_impl->open(method, url, async, user, password, ec);
+                } else
+                    request->m_impl->open(method, url, async, user, ec);
+            } else
+                request->m_impl->open(method, url, async, ec);
+
+            setDOMException(exec, ec);
+            return jsUndefined();
+        }
+        case JSXMLHttpRequest::Send: {
+            String body;
+
+            if (args.size() >= 1) {
+                if (args[0]->toObject(exec)->inherits(&JSDocument::info)) {
+                    Document* doc = static_cast<Document*>(static_cast<JSDocument*>(args[0]->toObject(exec))->impl());
+                    body = doc->toString().deprecatedString();
+                } else {
+                    // converting certain values (like null) to object can set an exception
+                    if (exec->hadException())
+                        exec->clearException();
+                    else
+                        body = args[0]->toString(exec);
+                }
+            }
+
+            request->m_impl->send(body, ec);
+            setDOMException(exec, ec);
+
+            return jsUndefined();
+        }
+        case JSXMLHttpRequest::SetRequestHeader:
+            if (args.size() < 2)
+                return throwError(exec, SyntaxError, "Not enough arguments");
+
+            request->m_impl->setRequestHeader(args[0]->toString(exec), args[1]->toString(exec), ec);
+            setDOMException(exec, ec);
+            return jsUndefined();
+
+        case JSXMLHttpRequest::OverrideMIMEType:
+            if (args.size() < 1)
+                return throwError(exec, SyntaxError, "Not enough arguments");
+
+            request->m_impl->overrideMIMEType(args[0]->toString(exec));
+            return jsUndefined();
+        
+        case JSXMLHttpRequest::AddEventListener: {
+            Document* doc = request->m_impl->document();
+            if (!doc)
+                return jsUndefined();
+            Frame* frame = doc->frame();
+            if (!frame)
+                return jsUndefined();
+            JSUnprotectedEventListener* listener = KJS::Window::retrieveWindow(frame)->findOrCreateJSUnprotectedEventListener(args[1], true);
+            if (!listener)
+                return jsUndefined();
+            request->m_impl->addEventListener(args[0]->toString(exec), listener, args[2]->toBoolean(exec));
+            return jsUndefined();
+        }
+        case JSXMLHttpRequest::RemoveEventListener: {
+            Document* doc = request->m_impl->document();
+            if (!doc)
+                return jsUndefined();
+            Frame* frame = doc->frame();
+            if (!frame)
+                return jsUndefined();
+            JSUnprotectedEventListener* listener = KJS::Window::retrieveWindow(frame)->findOrCreateJSUnprotectedEventListener(args[1], true);
+            if (!listener)
+                return jsUndefined();
+            request->m_impl->removeEventListener(args[0]->toString(exec), listener, args[2]->toBoolean(exec));
+            return jsUndefined();
+        }
+        case JSXMLHttpRequest::DispatchEvent: {
+            bool result = request->m_impl->dispatchEvent(toEvent(args[0]), ec);
+            setDOMException(exec, ec);
+            return jsBoolean(result);
+        }
+    }
+
+    return jsUndefined();
+}
+
+} // end namespace