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