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 "bindings/core/v8/V8XMLHttpRequest.h" 33 34#include "bindings/core/v8/ExceptionMessages.h" 35#include "bindings/core/v8/ExceptionState.h" 36#include "bindings/core/v8/V8Binding.h" 37#include "bindings/core/v8/V8Blob.h" 38#include "bindings/core/v8/V8Document.h" 39#include "bindings/core/v8/V8FormData.h" 40#include "bindings/core/v8/V8HTMLDocument.h" 41#include "bindings/core/v8/V8ReadableStream.h" 42#include "bindings/core/v8/V8Stream.h" 43#include "bindings/core/v8/custom/V8ArrayBufferCustom.h" 44#include "bindings/core/v8/custom/V8ArrayBufferViewCustom.h" 45#include "core/dom/Document.h" 46#include "core/inspector/InspectorInstrumentation.h" 47#include "core/streams/ReadableStream.h" 48#include "core/streams/Stream.h" 49#include "core/workers/WorkerGlobalScope.h" 50#include "core/xml/XMLHttpRequest.h" 51#include "wtf/ArrayBuffer.h" 52#include <v8.h> 53 54namespace blink { 55 56void V8XMLHttpRequest::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 57{ 58 ExecutionContext* context = currentExecutionContext(info.GetIsolate()); 59 60 RefPtr<SecurityOrigin> securityOrigin; 61 if (context->isDocument()) { 62 DOMWrapperWorld& world = DOMWrapperWorld::current(info.GetIsolate()); 63 if (world.isIsolatedWorld()) 64 securityOrigin = world.isolatedWorldSecurityOrigin(); 65 } 66 67 RefPtrWillBeRawPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context, securityOrigin); 68 69 v8::Handle<v8::Object> wrapper = info.Holder(); 70 V8DOMWrapper::associateObjectWithWrapper<V8XMLHttpRequest>(xmlHttpRequest.release(), &wrapperTypeInfo, wrapper, info.GetIsolate()); 71 info.GetReturnValue().Set(wrapper); 72} 73 74void V8XMLHttpRequest::responseTextAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) 75{ 76 XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toImpl(info.Holder()); 77 ExceptionState exceptionState(ExceptionState::GetterContext, "responseText", "XMLHttpRequest", info.Holder(), info.GetIsolate()); 78 ScriptString text = xmlHttpRequest->responseText(exceptionState); 79 if (exceptionState.throwIfNeeded()) 80 return; 81 if (text.isEmpty()) { 82 v8SetReturnValueString(info, emptyString(), info.GetIsolate()); 83 return; 84 } 85 v8SetReturnValue(info, text.v8Value()); 86} 87 88void V8XMLHttpRequest::responseAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) 89{ 90 XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toImpl(info.Holder()); 91 92 switch (xmlHttpRequest->responseTypeCode()) { 93 case XMLHttpRequest::ResponseTypeDefault: 94 case XMLHttpRequest::ResponseTypeText: 95 responseTextAttributeGetterCustom(info); 96 return; 97 98 case XMLHttpRequest::ResponseTypeJSON: 99 { 100 v8::Isolate* isolate = info.GetIsolate(); 101 102 ScriptString jsonSource = xmlHttpRequest->responseJSONSource(); 103 if (jsonSource.isEmpty()) { 104 v8SetReturnValue(info, v8::Null(isolate)); 105 return; 106 } 107 108 // Catch syntax error. 109 v8::TryCatch exceptionCatcher; 110 v8::Handle<v8::Value> json = v8::JSON::Parse(jsonSource.v8Value()); 111 if (exceptionCatcher.HasCaught() || json.IsEmpty()) 112 v8SetReturnValue(info, v8::Null(isolate)); 113 else 114 v8SetReturnValue(info, json); 115 return; 116 } 117 118 case XMLHttpRequest::ResponseTypeDocument: 119 { 120 ExceptionState exceptionState(ExceptionState::GetterContext, "response", "XMLHttpRequest", info.Holder(), info.GetIsolate()); 121 Document* document = xmlHttpRequest->responseXML(exceptionState); 122 if (exceptionState.throwIfNeeded()) 123 return; 124 v8SetReturnValueFast(info, document, xmlHttpRequest); 125 return; 126 } 127 128 case XMLHttpRequest::ResponseTypeBlob: 129 { 130 Blob* blob = xmlHttpRequest->responseBlob(); 131 v8SetReturnValueFast(info, blob, xmlHttpRequest); 132 return; 133 } 134 135 case XMLHttpRequest::ResponseTypeLegacyStream: 136 { 137 Stream* stream = xmlHttpRequest->responseLegacyStream(); 138 v8SetReturnValueFast(info, stream, xmlHttpRequest); 139 return; 140 } 141 142 case XMLHttpRequest::ResponseTypeStream: 143 { 144 ReadableStream* stream = xmlHttpRequest->responseStream(); 145 v8SetReturnValueFast(info, stream, xmlHttpRequest); 146 return; 147 } 148 149 case XMLHttpRequest::ResponseTypeArrayBuffer: 150 { 151 ArrayBuffer* arrayBuffer = xmlHttpRequest->responseArrayBuffer(); 152 if (arrayBuffer) { 153 arrayBuffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate()); 154 } 155 v8SetReturnValueFast(info, arrayBuffer, xmlHttpRequest); 156 return; 157 } 158 } 159} 160 161void V8XMLHttpRequest::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 162{ 163 // Four cases: 164 // open(method, url) 165 // open(method, url, async) 166 // open(method, url, async, user) 167 // open(method, url, async, user, passwd) 168 169 ExceptionState exceptionState(ExceptionState::ExecutionContext, "open", "XMLHttpRequest", info.Holder(), info.GetIsolate()); 170 171 if (info.Length() < 2) { 172 exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(2, info.Length())); 173 exceptionState.throwIfNeeded(); 174 return; 175 } 176 177 XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toImpl(info.Holder()); 178 179 TOSTRING_VOID(V8StringResource<>, method, info[0]); 180 TOSTRING_VOID(V8StringResource<>, urlstring, info[1]); 181 182 ExecutionContext* context = currentExecutionContext(info.GetIsolate()); 183 KURL url = context->completeURL(urlstring); 184 185 if (info.Length() >= 3) { 186 bool async = info[2]->BooleanValue(); 187 188 if (info.Length() >= 4 && !info[3]->IsUndefined()) { 189 TOSTRING_VOID(V8StringResource<TreatNullAsNullString>, user, info[3]); 190 191 if (info.Length() >= 5 && !info[4]->IsUndefined()) { 192 TOSTRING_VOID(V8StringResource<TreatNullAsNullString>, password, info[4]); 193 xmlHttpRequest->open(method, url, async, user, password, exceptionState); 194 } else { 195 xmlHttpRequest->open(method, url, async, user, exceptionState); 196 } 197 } else { 198 xmlHttpRequest->open(method, url, async, exceptionState); 199 } 200 } else { 201 xmlHttpRequest->open(method, url, exceptionState); 202 } 203 204 exceptionState.throwIfNeeded(); 205} 206 207static bool isDocumentType(v8::Handle<v8::Value> value, v8::Isolate* isolate) 208{ 209 // FIXME: add other document types. 210 return V8Document::hasInstance(value, isolate) || V8HTMLDocument::hasInstance(value, isolate); 211} 212 213void V8XMLHttpRequest::sendMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 214{ 215 XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toImpl(info.Holder()); 216 217 InspectorInstrumentation::willSendXMLHttpRequest(xmlHttpRequest->executionContext(), xmlHttpRequest->url()); 218 219 ExceptionState exceptionState(ExceptionState::ExecutionContext, "send", "XMLHttpRequest", info.Holder(), info.GetIsolate()); 220 if (info.Length() < 1) { 221 xmlHttpRequest->send(exceptionState); 222 } else { 223 v8::Handle<v8::Value> arg = info[0]; 224 if (isUndefinedOrNull(arg)) { 225 xmlHttpRequest->send(exceptionState); 226 } else if (isDocumentType(arg, info.GetIsolate())) { 227 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); 228 Document* document = V8Document::toImpl(object); 229 ASSERT(document); 230 xmlHttpRequest->send(document, exceptionState); 231 } else if (V8Blob::hasInstance(arg, info.GetIsolate())) { 232 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); 233 Blob* blob = V8Blob::toImpl(object); 234 ASSERT(blob); 235 xmlHttpRequest->send(blob, exceptionState); 236 } else if (V8FormData::hasInstance(arg, info.GetIsolate())) { 237 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); 238 DOMFormData* domFormData = V8FormData::toImpl(object); 239 ASSERT(domFormData); 240 xmlHttpRequest->send(domFormData, exceptionState); 241 } else if (V8ArrayBuffer::hasInstance(arg, info.GetIsolate())) { 242 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); 243 ArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(object); 244 ASSERT(arrayBuffer); 245 xmlHttpRequest->send(arrayBuffer, exceptionState); 246 } else if (V8ArrayBufferView::hasInstance(arg, info.GetIsolate())) { 247 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); 248 ArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object); 249 ASSERT(arrayBufferView); 250 xmlHttpRequest->send(arrayBufferView, exceptionState); 251 } else { 252 TOSTRING_VOID(V8StringResource<TreatNullAsNullString>, argString, arg); 253 xmlHttpRequest->send(argString, exceptionState); 254 } 255 } 256 257 exceptionState.throwIfNeeded(); 258} 259 260} // namespace blink 261