1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/ipc/StructuredCloneUtils.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,182 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* vim: set sw=4 ts=8 et tw=80 : */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "StructuredCloneUtils.h" 1.11 + 1.12 +#include "nsIDOMFile.h" 1.13 +#include "nsIDOMDOMException.h" 1.14 +#include "nsIMutable.h" 1.15 +#include "nsIXPConnect.h" 1.16 + 1.17 +#include "nsContentUtils.h" 1.18 +#include "nsJSEnvironment.h" 1.19 +#include "MainThreadUtils.h" 1.20 +#include "StructuredCloneTags.h" 1.21 +#include "jsapi.h" 1.22 + 1.23 +using namespace mozilla::dom; 1.24 + 1.25 +namespace { 1.26 + 1.27 +void 1.28 +Error(JSContext* aCx, uint32_t aErrorId) 1.29 +{ 1.30 + MOZ_ASSERT(NS_IsMainThread()); 1.31 + NS_DOMStructuredCloneError(aCx, aErrorId); 1.32 +} 1.33 + 1.34 +JSObject* 1.35 +Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag, 1.36 + uint32_t aData, void* aClosure) 1.37 +{ 1.38 + MOZ_ASSERT(NS_IsMainThread()); 1.39 + MOZ_ASSERT(aClosure); 1.40 + 1.41 + StructuredCloneClosure* closure = 1.42 + static_cast<StructuredCloneClosure*>(aClosure); 1.43 + 1.44 + if (aTag == SCTAG_DOM_FILE) { 1.45 + MOZ_ASSERT(aData < closure->mBlobs.Length()); 1.46 + 1.47 + nsCOMPtr<nsIDOMFile> file = do_QueryInterface(closure->mBlobs[aData]); 1.48 + MOZ_ASSERT(file); 1.49 + 1.50 +#ifdef DEBUG 1.51 + { 1.52 + // File should not be mutable. 1.53 + nsCOMPtr<nsIMutable> mutableFile = do_QueryInterface(file); 1.54 + bool isMutable; 1.55 + MOZ_ASSERT(NS_SUCCEEDED(mutableFile->GetMutable(&isMutable))); 1.56 + MOZ_ASSERT(!isMutable); 1.57 + } 1.58 +#endif 1.59 + 1.60 + JS::Rooted<JS::Value> wrappedFile(aCx); 1.61 + nsresult rv = nsContentUtils::WrapNative(aCx, file, &NS_GET_IID(nsIDOMFile), 1.62 + &wrappedFile); 1.63 + if (NS_FAILED(rv)) { 1.64 + Error(aCx, nsIDOMDOMException::DATA_CLONE_ERR); 1.65 + return nullptr; 1.66 + } 1.67 + 1.68 + return &wrappedFile.toObject(); 1.69 + } 1.70 + 1.71 + if (aTag == SCTAG_DOM_BLOB) { 1.72 + MOZ_ASSERT(aData < closure->mBlobs.Length()); 1.73 + 1.74 + nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(closure->mBlobs[aData]); 1.75 + MOZ_ASSERT(blob); 1.76 + 1.77 +#ifdef DEBUG 1.78 + { 1.79 + // Blob should not be mutable. 1.80 + nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(blob); 1.81 + bool isMutable; 1.82 + MOZ_ASSERT(NS_SUCCEEDED(mutableBlob->GetMutable(&isMutable))); 1.83 + MOZ_ASSERT(!isMutable); 1.84 + } 1.85 +#endif 1.86 + 1.87 + JS::Rooted<JS::Value> wrappedBlob(aCx); 1.88 + nsresult rv = nsContentUtils::WrapNative(aCx, blob, &NS_GET_IID(nsIDOMBlob), 1.89 + &wrappedBlob); 1.90 + if (NS_FAILED(rv)) { 1.91 + Error(aCx, nsIDOMDOMException::DATA_CLONE_ERR); 1.92 + return nullptr; 1.93 + } 1.94 + 1.95 + return &wrappedBlob.toObject(); 1.96 + } 1.97 + 1.98 + return NS_DOMReadStructuredClone(aCx, aReader, aTag, aData, nullptr); 1.99 +} 1.100 + 1.101 +bool 1.102 +Write(JSContext* aCx, JSStructuredCloneWriter* aWriter, 1.103 + JS::Handle<JSObject*> aObj, void* aClosure) 1.104 +{ 1.105 + MOZ_ASSERT(NS_IsMainThread()); 1.106 + MOZ_ASSERT(aClosure); 1.107 + 1.108 + StructuredCloneClosure* closure = 1.109 + static_cast<StructuredCloneClosure*>(aClosure); 1.110 + 1.111 + // See if this is a wrapped native. 1.112 + nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative; 1.113 + nsContentUtils::XPConnect()-> 1.114 + GetWrappedNativeOfJSObject(aCx, aObj, getter_AddRefs(wrappedNative)); 1.115 + 1.116 + if (wrappedNative) { 1.117 + // Get the raw nsISupports out of it. 1.118 + nsISupports* wrappedObject = wrappedNative->Native(); 1.119 + MOZ_ASSERT(wrappedObject); 1.120 + 1.121 + // See if the wrapped native is a nsIDOMFile. 1.122 + nsCOMPtr<nsIDOMFile> file = do_QueryInterface(wrappedObject); 1.123 + if (file) { 1.124 + nsCOMPtr<nsIMutable> mutableFile = do_QueryInterface(file); 1.125 + if (mutableFile && 1.126 + NS_SUCCEEDED(mutableFile->SetMutable(false)) && 1.127 + JS_WriteUint32Pair(aWriter, SCTAG_DOM_FILE, 1.128 + closure->mBlobs.Length())) { 1.129 + closure->mBlobs.AppendElement(file); 1.130 + return true; 1.131 + } 1.132 + } 1.133 + 1.134 + // See if the wrapped native is a nsIDOMBlob. 1.135 + nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(wrappedObject); 1.136 + if (blob) { 1.137 + nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(blob); 1.138 + if (mutableBlob && 1.139 + NS_SUCCEEDED(mutableBlob->SetMutable(false)) && 1.140 + JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB, 1.141 + closure->mBlobs.Length())) { 1.142 + closure->mBlobs.AppendElement(blob); 1.143 + return true; 1.144 + } 1.145 + } 1.146 + } 1.147 + 1.148 + return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nullptr); 1.149 +} 1.150 + 1.151 +JSStructuredCloneCallbacks gCallbacks = { 1.152 + Read, 1.153 + Write, 1.154 + Error, 1.155 + nullptr, 1.156 + nullptr, 1.157 + nullptr 1.158 +}; 1.159 + 1.160 +} // anonymous namespace 1.161 + 1.162 +namespace mozilla { 1.163 +namespace dom { 1.164 + 1.165 +bool 1.166 +ReadStructuredClone(JSContext* aCx, uint64_t* aData, size_t aDataLength, 1.167 + const StructuredCloneClosure& aClosure, 1.168 + JS::MutableHandle<JS::Value> aClone) 1.169 +{ 1.170 + void* closure = &const_cast<StructuredCloneClosure&>(aClosure); 1.171 + return !!JS_ReadStructuredClone(aCx, aData, aDataLength, 1.172 + JS_STRUCTURED_CLONE_VERSION, aClone, 1.173 + &gCallbacks, closure); 1.174 +} 1.175 + 1.176 +bool 1.177 +WriteStructuredClone(JSContext* aCx, JS::Handle<JS::Value> aSource, 1.178 + JSAutoStructuredCloneBuffer& aBuffer, 1.179 + StructuredCloneClosure& aClosure) 1.180 +{ 1.181 + return aBuffer.write(aCx, aSource, &gCallbacks, &aClosure); 1.182 +} 1.183 + 1.184 +} // namespace dom 1.185 +} // namespace mozilla