dom/ipc/StructuredCloneUtils.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* vim: set sw=4 ts=8 et tw=80 : */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "StructuredCloneUtils.h"
     9 #include "nsIDOMFile.h"
    10 #include "nsIDOMDOMException.h"
    11 #include "nsIMutable.h"
    12 #include "nsIXPConnect.h"
    14 #include "nsContentUtils.h"
    15 #include "nsJSEnvironment.h"
    16 #include "MainThreadUtils.h"
    17 #include "StructuredCloneTags.h"
    18 #include "jsapi.h"
    20 using namespace mozilla::dom;
    22 namespace {
    24 void
    25 Error(JSContext* aCx, uint32_t aErrorId)
    26 {
    27   MOZ_ASSERT(NS_IsMainThread());
    28   NS_DOMStructuredCloneError(aCx, aErrorId);
    29 }
    31 JSObject*
    32 Read(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag,
    33      uint32_t aData, void* aClosure)
    34 {
    35   MOZ_ASSERT(NS_IsMainThread());
    36   MOZ_ASSERT(aClosure);
    38   StructuredCloneClosure* closure =
    39     static_cast<StructuredCloneClosure*>(aClosure);
    41   if (aTag == SCTAG_DOM_FILE) {
    42     MOZ_ASSERT(aData < closure->mBlobs.Length());
    44     nsCOMPtr<nsIDOMFile> file = do_QueryInterface(closure->mBlobs[aData]);
    45     MOZ_ASSERT(file);
    47 #ifdef DEBUG
    48     {
    49       // File should not be mutable.
    50       nsCOMPtr<nsIMutable> mutableFile = do_QueryInterface(file);
    51       bool isMutable;
    52       MOZ_ASSERT(NS_SUCCEEDED(mutableFile->GetMutable(&isMutable)));
    53       MOZ_ASSERT(!isMutable);
    54     }
    55 #endif
    57     JS::Rooted<JS::Value> wrappedFile(aCx);
    58     nsresult rv = nsContentUtils::WrapNative(aCx, file, &NS_GET_IID(nsIDOMFile),
    59                                              &wrappedFile);
    60     if (NS_FAILED(rv)) {
    61       Error(aCx, nsIDOMDOMException::DATA_CLONE_ERR);
    62       return nullptr;
    63     }
    65     return &wrappedFile.toObject();
    66   }
    68   if (aTag == SCTAG_DOM_BLOB) {
    69     MOZ_ASSERT(aData < closure->mBlobs.Length());
    71     nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(closure->mBlobs[aData]);
    72     MOZ_ASSERT(blob);
    74 #ifdef DEBUG
    75     {
    76       // Blob should not be mutable.
    77       nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(blob);
    78       bool isMutable;
    79       MOZ_ASSERT(NS_SUCCEEDED(mutableBlob->GetMutable(&isMutable)));
    80       MOZ_ASSERT(!isMutable);
    81     }
    82 #endif
    84     JS::Rooted<JS::Value> wrappedBlob(aCx);
    85     nsresult rv = nsContentUtils::WrapNative(aCx, blob, &NS_GET_IID(nsIDOMBlob),
    86                                              &wrappedBlob);
    87     if (NS_FAILED(rv)) {
    88       Error(aCx, nsIDOMDOMException::DATA_CLONE_ERR);
    89       return nullptr;
    90     }
    92     return &wrappedBlob.toObject();
    93   }
    95   return NS_DOMReadStructuredClone(aCx, aReader, aTag, aData, nullptr);
    96 }
    98 bool
    99 Write(JSContext* aCx, JSStructuredCloneWriter* aWriter,
   100       JS::Handle<JSObject*> aObj, void* aClosure)
   101 {
   102   MOZ_ASSERT(NS_IsMainThread());
   103   MOZ_ASSERT(aClosure);
   105   StructuredCloneClosure* closure =
   106     static_cast<StructuredCloneClosure*>(aClosure);
   108   // See if this is a wrapped native.
   109   nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
   110   nsContentUtils::XPConnect()->
   111     GetWrappedNativeOfJSObject(aCx, aObj, getter_AddRefs(wrappedNative));
   113   if (wrappedNative) {
   114     // Get the raw nsISupports out of it.
   115     nsISupports* wrappedObject = wrappedNative->Native();
   116     MOZ_ASSERT(wrappedObject);
   118     // See if the wrapped native is a nsIDOMFile.
   119     nsCOMPtr<nsIDOMFile> file = do_QueryInterface(wrappedObject);
   120     if (file) {
   121       nsCOMPtr<nsIMutable> mutableFile = do_QueryInterface(file);
   122       if (mutableFile &&
   123           NS_SUCCEEDED(mutableFile->SetMutable(false)) &&
   124           JS_WriteUint32Pair(aWriter, SCTAG_DOM_FILE,
   125                              closure->mBlobs.Length())) {
   126         closure->mBlobs.AppendElement(file);
   127         return true;
   128       }
   129     }
   131     // See if the wrapped native is a nsIDOMBlob.
   132     nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(wrappedObject);
   133     if (blob) {
   134       nsCOMPtr<nsIMutable> mutableBlob = do_QueryInterface(blob);
   135       if (mutableBlob &&
   136           NS_SUCCEEDED(mutableBlob->SetMutable(false)) &&
   137           JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB,
   138                              closure->mBlobs.Length())) {
   139         closure->mBlobs.AppendElement(blob);
   140         return true;
   141       }
   142     }
   143   }
   145   return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nullptr);
   146 }
   148 JSStructuredCloneCallbacks gCallbacks = {
   149   Read,
   150   Write,
   151   Error,
   152   nullptr,
   153   nullptr,
   154   nullptr
   155 };
   157 } // anonymous namespace
   159 namespace mozilla {
   160 namespace dom {
   162 bool
   163 ReadStructuredClone(JSContext* aCx, uint64_t* aData, size_t aDataLength,
   164                     const StructuredCloneClosure& aClosure,
   165                     JS::MutableHandle<JS::Value> aClone)
   166 {
   167   void* closure = &const_cast<StructuredCloneClosure&>(aClosure);
   168   return !!JS_ReadStructuredClone(aCx, aData, aDataLength,
   169                                   JS_STRUCTURED_CLONE_VERSION, aClone,
   170                                   &gCallbacks, closure);
   171 }
   173 bool
   174 WriteStructuredClone(JSContext* aCx, JS::Handle<JS::Value> aSource,
   175                      JSAutoStructuredCloneBuffer& aBuffer,
   176                      StructuredCloneClosure& aClosure)
   177 {
   178   return aBuffer.write(aCx, aSource, &gCallbacks, &aClosure);
   179 }
   181 } // namespace dom
   182 } // namespace mozilla

mercurial