Home | History | Annotate | Download | only in custom
      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 "V8XMLHttpRequest.h"
     33 
     34 #include "V8Blob.h"
     35 #include "V8Document.h"
     36 #include "V8FormData.h"
     37 #include "V8HTMLDocument.h"
     38 #include "bindings/v8/ExceptionState.h"
     39 #include "bindings/v8/V8Binding.h"
     40 #include "bindings/v8/V8Utilities.h"
     41 #include "bindings/v8/custom/V8ArrayBufferCustom.h"
     42 #include "bindings/v8/custom/V8ArrayBufferViewCustom.h"
     43 #include "core/dom/Document.h"
     44 #include "core/inspector/InspectorInstrumentation.h"
     45 #include "core/page/Frame.h"
     46 #include "core/workers/WorkerGlobalScope.h"
     47 #include "core/xml/XMLHttpRequest.h"
     48 #include "wtf/ArrayBuffer.h"
     49 
     50 namespace WebCore {
     51 
     52 void V8XMLHttpRequest::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
     53 {
     54     ScriptExecutionContext* context = getScriptExecutionContext();
     55 
     56     RefPtr<SecurityOrigin> securityOrigin;
     57     if (context->isDocument()) {
     58         if (DOMWrapperWorld* world = isolatedWorldForEnteredContext())
     59             securityOrigin = world->isolatedWorldSecurityOrigin();
     60     }
     61 
     62     RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context, securityOrigin);
     63 
     64     v8::Handle<v8::Object> wrapper = args.Holder();
     65     V8DOMWrapper::associateObjectWithWrapper<V8XMLHttpRequest>(xmlHttpRequest.release(), &info, wrapper, args.GetIsolate(), WrapperConfiguration::Dependent);
     66     args.GetReturnValue().Set(wrapper);
     67 }
     68 
     69 void V8XMLHttpRequest::responseTextAttrGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
     70 {
     71     XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(info.Holder());
     72     ExceptionState es(info.GetIsolate());
     73     ScriptValue text = xmlHttpRequest->responseText(es);
     74     if (es.throwIfNeeded())
     75         return;
     76     if (text.hasNoValue()) {
     77         v8SetReturnValueString(info, emptyString(), info.GetIsolate());
     78         return;
     79     }
     80     v8SetReturnValue(info, text.v8Value());
     81 }
     82 
     83 void V8XMLHttpRequest::responseAttrGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
     84 {
     85     XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(info.Holder());
     86 
     87     switch (xmlHttpRequest->responseTypeCode()) {
     88     case XMLHttpRequest::ResponseTypeDefault:
     89     case XMLHttpRequest::ResponseTypeText:
     90         responseTextAttrGetterCustom(name, info);
     91         return;
     92 
     93     case XMLHttpRequest::ResponseTypeDocument:
     94         {
     95             ExceptionState es(info.GetIsolate());
     96             Document* document = xmlHttpRequest->responseXML(es);
     97             if (es.throwIfNeeded())
     98                 return;
     99             v8SetReturnValue(info, toV8Fast(document, info, xmlHttpRequest));
    100             return;
    101         }
    102 
    103     case XMLHttpRequest::ResponseTypeBlob:
    104         {
    105             ExceptionState es(info.GetIsolate());
    106             Blob* blob = xmlHttpRequest->responseBlob(es);
    107             if (es.throwIfNeeded())
    108                 return;
    109             v8SetReturnValue(info, toV8Fast(blob, info, xmlHttpRequest));
    110             return;
    111         }
    112 
    113     case XMLHttpRequest::ResponseTypeArrayBuffer:
    114         {
    115             ExceptionState es(info.GetIsolate());
    116             ArrayBuffer* arrayBuffer = xmlHttpRequest->responseArrayBuffer(es);
    117             if (es.throwIfNeeded())
    118                 return;
    119             if (arrayBuffer && !arrayBuffer->hasDeallocationObserver()) {
    120                 arrayBuffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instance());
    121                 v8::V8::AdjustAmountOfExternalAllocatedMemory(arrayBuffer->byteLength());
    122             }
    123             v8SetReturnValue(info, toV8Fast(arrayBuffer, info, xmlHttpRequest));
    124             return;
    125         }
    126     }
    127 }
    128 
    129 void V8XMLHttpRequest::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    130 {
    131     // Four cases:
    132     // open(method, url)
    133     // open(method, url, async)
    134     // open(method, url, async, user)
    135     // open(method, url, async, user, passwd)
    136 
    137     if (args.Length() < 2) {
    138         throwNotEnoughArgumentsError(args.GetIsolate());
    139         return;
    140     }
    141 
    142     XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(args.Holder());
    143 
    144     String method = toWebCoreString(args[0]);
    145     String urlstring = toWebCoreString(args[1]);
    146 
    147     ScriptExecutionContext* context = getScriptExecutionContext();
    148     KURL url = context->completeURL(urlstring);
    149 
    150     ExceptionState es(args.GetIsolate());
    151 
    152     if (args.Length() >= 3) {
    153         bool async = args[2]->BooleanValue();
    154 
    155         if (args.Length() >= 4 && !args[3]->IsUndefined()) {
    156             String user = toWebCoreStringWithNullCheck(args[3]);
    157 
    158             if (args.Length() >= 5 && !args[4]->IsUndefined()) {
    159                 String passwd = toWebCoreStringWithNullCheck(args[4]);
    160                 xmlHttpRequest->open(method, url, async, user, passwd, es);
    161             } else {
    162                 xmlHttpRequest->open(method, url, async, user, es);
    163             }
    164         } else {
    165             xmlHttpRequest->open(method, url, async, es);
    166         }
    167     } else {
    168         xmlHttpRequest->open(method, url, es);
    169     }
    170 
    171     es.throwIfNeeded();
    172 }
    173 
    174 static bool isDocumentType(v8::Handle<v8::Value> value, v8::Isolate* isolate, WrapperWorldType currentWorldType)
    175 {
    176     // FIXME: add other document types.
    177     return V8Document::HasInstance(value, isolate, currentWorldType) || V8HTMLDocument::HasInstance(value, isolate, currentWorldType);
    178 }
    179 
    180 void V8XMLHttpRequest::sendMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args)
    181 {
    182     XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(args.Holder());
    183 
    184     InspectorInstrumentation::willSendXMLHttpRequest(xmlHttpRequest->scriptExecutionContext(), xmlHttpRequest->url());
    185 
    186     ExceptionState es(args.GetIsolate());
    187     if (args.Length() < 1)
    188         xmlHttpRequest->send(es);
    189     else {
    190         v8::Handle<v8::Value> arg = args[0];
    191         WrapperWorldType currentWorldType = worldType(args.GetIsolate());
    192         if (isUndefinedOrNull(arg))
    193             xmlHttpRequest->send(es);
    194         else if (isDocumentType(arg, args.GetIsolate(), currentWorldType)) {
    195             v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg);
    196             Document* document = V8Document::toNative(object);
    197             ASSERT(document);
    198             xmlHttpRequest->send(document, es);
    199         } else if (V8Blob::HasInstance(arg, args.GetIsolate(), currentWorldType)) {
    200             v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg);
    201             Blob* blob = V8Blob::toNative(object);
    202             ASSERT(blob);
    203             xmlHttpRequest->send(blob, es);
    204         } else if (V8FormData::HasInstance(arg, args.GetIsolate(), currentWorldType)) {
    205             v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg);
    206             DOMFormData* domFormData = V8FormData::toNative(object);
    207             ASSERT(domFormData);
    208             xmlHttpRequest->send(domFormData, es);
    209         } else if (V8ArrayBuffer::HasInstance(arg, args.GetIsolate(), currentWorldType)) {
    210             v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg);
    211             ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(object);
    212             ASSERT(arrayBuffer);
    213             xmlHttpRequest->send(arrayBuffer, es);
    214         } else if (V8ArrayBufferView::HasInstance(arg, args.GetIsolate(), currentWorldType)) {
    215             v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg);
    216             ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(object);
    217             ASSERT(arrayBufferView);
    218             xmlHttpRequest->send(arrayBufferView, es);
    219         } else
    220             xmlHttpRequest->send(toWebCoreStringWithNullCheck(arg), es);
    221     }
    222 
    223     es.throwIfNeeded();
    224 }
    225 
    226 } // namespace WebCore
    227