Bug 1275398 - Use shmem for sending image data in IPCDataTransfer. r=nical, a=lizzard
authorCervantes Yu <cyu@mozilla.com>
Thu, 16 Jun 2016 00:57:46 +0800
changeset 339806 d36dbe26035d26757ba6797ba446c92f807aeeca
parent 339805 01f2dde06c5fd93b38c0d80b6028210b48dd3f4a
child 339807 e883641e228b3c5829752ea96c8900bdb88a4b94
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical, lizzard
bugs1275398
milestone49.0a2
Bug 1275398 - Use shmem for sending image data in IPCDataTransfer. r=nical, a=lizzard MozReview-Commit-ID: 9XETnSBXxEW
dom/base/nsContentUtils.cpp
dom/ipc/ContentBridgeChild.h
dom/ipc/ContentBridgeParent.h
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/DOMTypes.ipdlh
dom/ipc/TabParent.cpp
dom/ipc/nsIContentChild.h
dom/ipc/nsIContentParent.h
ipc/glue/Shmem.cpp
widget/nsClipboardProxy.cpp
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -7314,31 +7314,31 @@ nsContentUtils::IsFileImage(nsIFile* aFi
 
   return StringBeginsWith(aType, NS_LITERAL_CSTRING("image/"));
 }
 
 nsresult
 nsContentUtils::DataTransferItemToImage(const IPCDataTransferItem& aItem,
                                         imgIContainer** aContainer)
 {
-  MOZ_ASSERT(aItem.data().type() == IPCDataTransferData::TnsCString);
+  MOZ_ASSERT(aItem.data().type() == IPCDataTransferData::TShmem);
   MOZ_ASSERT(IsFlavorImage(aItem.flavor()));
 
   const IPCDataTransferImage& imageDetails = aItem.imageDetails();
   const IntSize size(imageDetails.width(), imageDetails.height());
   if (!size.width || !size.height) {
     return NS_ERROR_FAILURE;
   }
 
-  const nsCString& text = aItem.data().get_nsCString();
+  Shmem data = aItem.data().get_Shmem();
 
   RefPtr<DataSourceSurface> image =
       CreateDataSourceSurfaceFromData(size,
                                       static_cast<SurfaceFormat>(imageDetails.format()),
-                                      reinterpret_cast<const uint8_t*>(text.BeginReading()),
+                                      data.get<uint8_t>(),
                                       imageDetails.stride());
 
   RefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(image, size);
   nsCOMPtr<imgIContainer> imageContainer =
     image::ImageOps::CreateFromDrawable(drawable);
   imageContainer.forget(aContainer);
 
   return NS_OK;
@@ -7349,16 +7349,41 @@ nsContentUtils::IsFlavorImage(const nsAC
 {
   return aFlavor.EqualsLiteral(kNativeImageMime) ||
          aFlavor.EqualsLiteral(kJPEGImageMime) ||
          aFlavor.EqualsLiteral(kJPGImageMime) ||
          aFlavor.EqualsLiteral(kPNGImageMime) ||
          aFlavor.EqualsLiteral(kGIFImageMime);
 }
 
+static Shmem
+ConvertToShmem(mozilla::dom::nsIContentChild* aChild,
+               mozilla::dom::nsIContentParent* aParent,
+               const nsACString& aInput)
+{
+  MOZ_ASSERT((aChild && !aParent) || (!aChild && aParent));
+
+  IShmemAllocator* allocator =
+    aChild ? static_cast<IShmemAllocator*>(aChild)
+           : static_cast<IShmemAllocator*>(aParent);
+
+  Shmem result;
+  if (!allocator->AllocShmem(aInput.Length() + 1,
+                             SharedMemory::TYPE_BASIC,
+                             &result)) {
+    return result;
+  }
+
+  memcpy(result.get<char>(),
+         aInput.BeginReading(),
+         aInput.Length() + 1);
+
+  return result;
+}
+
 void
 nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
                                               IPCDataTransfer* aIPCDataTransfer,
                                               bool aInSyncMessage,
                                               mozilla::dom::nsIContentChild* aChild,
                                               mozilla::dom::nsIContentParent* aParent)
 {
   MOZ_ASSERT((aChild && !aParent) || (!aChild && aParent));
@@ -7393,33 +7418,45 @@ nsContentUtils::TransferableToIPCTransfe
           IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
           item->flavor() = flavorStr;
           item->data() = dataAsString;
         } else if (ctext) {
           nsAutoCString dataAsString;
           ctext->GetData(dataAsString);
           IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
           item->flavor() = flavorStr;
-          item->data() = dataAsString;
+
+          Shmem dataAsShmem = ConvertToShmem(aChild, aParent, dataAsString);
+          if (!dataAsShmem.IsReadable() || !dataAsShmem.Size<char>()) {
+            continue;
+          }
+
+          item->data() = dataAsShmem;
         } else {
           nsCOMPtr<nsISupportsInterfacePointer> sip =
             do_QueryInterface(data);
           if (sip) {
             sip->GetData(getter_AddRefs(data));
           }
 
           // Images to be pasted on the clipboard are nsIInputStreams
           nsCOMPtr<nsIInputStream> stream(do_QueryInterface(data));
           if (stream) {
             IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
             item->flavor() = flavorStr;
 
             nsCString imageData;
             NS_ConsumeStream(stream, UINT32_MAX, imageData);
-            item->data() = imageData;
+
+            Shmem imageDataShmem = ConvertToShmem(aChild, aParent, imageData);
+            if (!imageDataShmem.IsReadable() || !imageDataShmem.Size<char>()) {
+              continue;
+            }
+
+            item->data() = imageDataShmem;
             continue;
           }
 
           // Images to be placed on the clipboard are imgIContainers.
           nsCOMPtr<imgIContainer> image(do_QueryInterface(data));
           if (image) {
             RefPtr<mozilla::gfx::SourceSurface> surface =
               image->GetFrame(imgIContainer::FRAME_CURRENT,
@@ -7429,25 +7466,27 @@ nsContentUtils::TransferableToIPCTransfe
             }
             RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
               surface->GetDataSurface();
             if (!dataSurface) {
               continue;
             }
             size_t length;
             int32_t stride;
-            mozilla::UniquePtr<char[]> surfaceData =
-              nsContentUtils::GetSurfaceData(WrapNotNull(dataSurface), &length,
-                                             &stride);
+            Shmem surfaceData;
+            IShmemAllocator* allocator = aChild ? static_cast<IShmemAllocator*>(aChild)
+                                                : static_cast<IShmemAllocator*>(aParent);
+            GetSurfaceData(dataSurface, &length, &stride,
+                           allocator,
+                           &surfaceData);
 
             IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
             item->flavor() = flavorStr;
             // Turn item->data() into an nsCString prior to accessing it.
-            item->data() = EmptyCString();
-            item->data().get_nsCString().Adopt(surfaceData.release(), length);
+            item->data() = surfaceData;
 
             IPCDataTransferImage& imageDetails = item->imageDetails();
             mozilla::gfx::IntSize size = dataSurface->GetSize();
             imageDetails.width() = size.width;
             imageDetails.height() = size.height;
             imageDetails.stride() = stride;
             imageDetails.format() = static_cast<uint8_t>(dataSurface->GetFormat());
 
@@ -7465,17 +7504,19 @@ nsContentUtils::TransferableToIPCTransfe
             // called from editor and send over images as raw data.
             if (aInSyncMessage) {
               nsAutoCString type;
               if (IsFileImage(file, type)) {
                 IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
                 item->flavor() = type;
                 nsAutoCString data;
                 SlurpFileToString(file, data);
-                item->data() = data;
+
+                Shmem dataAsShmem = ConvertToShmem(aChild, aParent, data);
+                item->data() = dataAsShmem;
               }
 
               continue;
             }
 
             blobImpl = new BlobImplFile(file, false);
             ErrorResult rv;
             // Ensure that file data is cached no that the content process
@@ -7524,17 +7565,17 @@ nsContentUtils::TransferableToIPCTransfe
             if (flavorStr.EqualsLiteral(kFilePromiseMime)) {
               IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
               item->flavor() = flavorStr;
               item->data() = NS_ConvertUTF8toUTF16(flavorStr);
             } else if (!data) {
               // Empty element, transfer only the flavor
               IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
               item->flavor() = flavorStr;
-              item->data() = EmptyCString();
+              item->data() = nsString();
               continue;
             }
           }
         }
       }
     }
   }
 }
--- a/dom/ipc/ContentBridgeChild.h
+++ b/dom/ipc/ContentBridgeChild.h
@@ -41,16 +41,18 @@ public:
   virtual bool SendPBrowserConstructor(PBrowserChild* aActor,
                                        const TabId& aTabId,
                                        const IPCTabContext& aContext,
                                        const uint32_t& aChromeFlags,
                                        const ContentParentId& aCpID,
                                        const bool& aIsForApp,
                                        const bool& aIsForBrowser) override;
 
+  FORWARD_SHMEM_ALLOCATOR_TO(PContentBridgeChild)
+
 protected:
   virtual ~ContentBridgeChild();
 
   virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
                                             const IPCTabContext& aContext,
                                             const uint32_t& aChromeFlags,
                                             const ContentParentId& aCpID,
                                             const bool& aIsForApp,
--- a/dom/ipc/ContentBridgeParent.h
+++ b/dom/ipc/ContentBridgeParent.h
@@ -41,16 +41,18 @@ public:
   SendPBrowserConstructor(PBrowserParent* aActor,
                           const TabId& aTabId,
                           const IPCTabContext& aContext,
                           const uint32_t& aChromeFlags,
                           const ContentParentId& aCpID,
                           const bool& aIsForApp,
                           const bool& aIsForBrowser) override;
 
+  FORWARD_SHMEM_ALLOCATOR_TO(PContentBridgeParent)
+
   jsipc::CPOWManager* GetCPOWManager() override;
 
   virtual ContentParentId ChildID() const override
   {
     return mChildID;
   }
   virtual bool IsForApp() const override
   {
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -3302,19 +3302,20 @@ ContentChild::RecvInvokeDragSession(nsTA
       for (uint32_t i = 0; i < aTransfers.Length(); ++i) {
         auto& items = aTransfers[i].items();
         for (uint32_t j = 0; j < items.Length(); ++j) {
           const IPCDataTransferItem& item = items[j];
           RefPtr<nsVariantCC> variant = new nsVariantCC();
           if (item.data().type() == IPCDataTransferData::TnsString) {
             const nsString& data = item.data().get_nsString();
             variant->SetAsAString(data);
-          } else if (item.data().type() == IPCDataTransferData::TnsCString) {
-            const nsCString& data = item.data().get_nsCString();
-            variant->SetAsACString(data);
+          } else if (item.data().type() == IPCDataTransferData::TShmem) {
+            Shmem data = item.data().get_Shmem();
+            variant->SetAsACString(nsDependentCString(data.get<char>(), data.Size<char>()));
+            Unused << DeallocShmem(data);
           } else if (item.data().type() == IPCDataTransferData::TPBlobChild) {
             BlobChild* blob = static_cast<BlobChild*>(item.data().get_PBlobChild());
             RefPtr<BlobImpl> blobImpl = blob->GetBlobImpl();
             variant->SetAsISupports(blobImpl);
           } else {
             continue;
           }
           dataTransfer->SetDataWithPrincipalFromOtherProcess(
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -582,16 +582,18 @@ public:
   virtual bool RecvPBrowserConstructor(PBrowserChild* aCctor,
                                        const TabId& aTabId,
                                        const IPCTabContext& aContext,
                                        const uint32_t& aChromeFlags,
                                        const ContentParentId& aCpID,
                                        const bool& aIsForApp,
                                        const bool& aIsForBrowser) override;
 
+  FORWARD_SHMEM_ALLOCATOR_TO(PContentChild)
+
   void GetAvailableDictionaries(InfallibleTArray<nsString>& aDictionaries);
 
   PBrowserOrId
   GetBrowserOrId(TabChild* aTabChild);
 
   virtual POfflineCacheUpdateChild*
   AllocPOfflineCacheUpdateChild(const URIParams& manifestURI,
                                 const URIParams& documentURI,
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2786,17 +2786,17 @@ ContentParent::RecvSetClipboard(const IP
       const nsString& text = item.data().get_nsString();
       rv = dataWrapper->SetData(text);
       NS_ENSURE_SUCCESS(rv, true);
 
       rv = trans->SetTransferData(item.flavor().get(), dataWrapper,
                                   text.Length() * sizeof(char16_t));
 
       NS_ENSURE_SUCCESS(rv, true);
-    } else if (item.data().type() == IPCDataTransferData::TnsCString) {
+    } else if (item.data().type() == IPCDataTransferData::TShmem) {
       if (nsContentUtils::IsFlavorImage(item.flavor())) {
         nsCOMPtr<imgIContainer> imageContainer;
         rv = nsContentUtils::DataTransferItemToImage(item,
                                                      getter_AddRefs(imageContainer));
         NS_ENSURE_SUCCESS(rv, true);
 
         nsCOMPtr<nsISupportsInterfacePointer> imgPtr =
           do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID);
@@ -2806,24 +2806,29 @@ ContentParent::RecvSetClipboard(const IP
         NS_ENSURE_SUCCESS(rv, true);
 
         trans->SetTransferData(item.flavor().get(), imgPtr, sizeof(nsISupports*));
       } else {
         nsCOMPtr<nsISupportsCString> dataWrapper =
           do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
         NS_ENSURE_SUCCESS(rv, true);
 
-        const nsCString& text = item.data().get_nsCString();
+        // The buffer contains the terminating null.
+        Shmem itemData = item.data().get_Shmem();
+        const nsDependentCString text(itemData.get<char>(),
+                                      itemData.Size<char>());
         rv = dataWrapper->SetData(text);
         NS_ENSURE_SUCCESS(rv, true);
 
         rv = trans->SetTransferData(item.flavor().get(), dataWrapper, text.Length());
 
         NS_ENSURE_SUCCESS(rv, true);
       }
+
+      Unused << DeallocShmem(item.data().get_Shmem());
     }
   }
 
   trans->SetIsPrivateData(aIsPrivateData);
 
   clipboard->SetData(trans, nullptr, aWhichClipboard);
   return true;
 }
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -559,16 +559,18 @@ private:
       const TabId& aTabId,
       const IPCTabContext& context,
       const uint32_t& chromeFlags,
       const ContentParentId& aCpId,
       const bool& aIsForApp,
       const bool& aIsForBrowser) override;
   using PContentParent::SendPTestShellConstructor;
 
+  FORWARD_SHMEM_ALLOCATOR_TO(PContentParent)
+
   // No more than one of !!aApp, aIsForBrowser, and aIsForPreallocated may be
   // true.
   ContentParent(mozIApplication* aApp,
                 ContentParent* aOpener,
                 bool aIsForBrowser,
                 bool aIsForPreallocated,
                 bool aIsNuwaProcess = false);
 
--- a/dom/ipc/DOMTypes.ipdlh
+++ b/dom/ipc/DOMTypes.ipdlh
@@ -139,17 +139,17 @@ union BlobConstructorParams
 {
   ChildBlobConstructorParams;
   ParentBlobConstructorParams;
 };
 
 union IPCDataTransferData
 {
   nsString;  // text
-  nsCString; // images
+  Shmem;     // images using Shmem
   PBlob;     // files
 };
 
 struct IPCDataTransferImage
 {
   uint32_t width;
   uint32_t height;
   uint32_t stride;
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -3290,30 +3290,33 @@ TabParent::AddInitialDnDDataTo(DataTrans
           new nsContentAreaDragDropDataProvider();
         variant->SetAsISupports(flavorDataProvider);
       } else if (item.data().type() == IPCDataTransferData::TnsString) {
         variant->SetAsAString(item.data().get_nsString());
       } else if (item.data().type() == IPCDataTransferData::TPBlobParent) {
         auto* parent = static_cast<BlobParent*>(item.data().get_PBlobParent());
         RefPtr<BlobImpl> impl = parent->GetBlobImpl();
         variant->SetAsISupports(impl);
-      } else if (item.data().type() == IPCDataTransferData::TnsCString) {
+      } else if (item.data().type() == IPCDataTransferData::TShmem) {
         if (nsContentUtils::IsFlavorImage(item.flavor())) {
           // An image! Get the imgIContainer for it and set it in the variant.
           nsCOMPtr<imgIContainer> imageContainer;
           nsresult rv =
             nsContentUtils::DataTransferItemToImage(item,
                                                     getter_AddRefs(imageContainer));
           if (NS_FAILED(rv)) {
             continue;
           }
           variant->SetAsISupports(imageContainer);
         } else {
-          variant->SetAsACString(item.data().get_nsCString());
+          Shmem data = item.data().get_Shmem();
+          variant->SetAsACString(nsDependentCString(data.get<char>(), data.Size<char>()));
         }
+
+        mozilla::Unused << DeallocShmem(item.data().get_Shmem());
       }
 
       // Using system principal here, since once the data is on parent process
       // side, it can be handled as being from browser chrome or OS.
       aDataTransfer->SetDataWithPrincipalFromOtherProcess(NS_ConvertUTF8toUTF16(item.flavor()),
                                                           variant, i,
                                                           nsContentUtils::GetSystemPrincipal());
     }
--- a/dom/ipc/nsIContentChild.h
+++ b/dom/ipc/nsIContentChild.h
@@ -7,29 +7,33 @@
 #ifndef mozilla_dom_nsIContentChild_h
 #define mozilla_dom_nsIContentChild_h
 
 #include "mozilla/dom/ipc/IdType.h"
 
 #include "nsISupports.h"
 #include "nsTArrayForwardDeclare.h"
 #include "mozilla/dom/CPOWManagerGetter.h"
+#include "mozilla/ipc/Shmem.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 
 #define NS_ICONTENTCHILD_IID                                    \
   { 0x4eed2e73, 0x94ba, 0x48a8,                                 \
     { 0xa2, 0xd1, 0xa5, 0xed, 0x86, 0xd7, 0xbb, 0xe4 } }
 
 class nsString;
 
 namespace IPC {
 class Principal;
 } // namespace IPC
 
 namespace mozilla {
+namespace ipc {
+class Shmem;
+} // namespace ipc
 
 namespace jsipc {
 class PJavaScriptChild;
 class CpowEntry;
 } // namespace jsipc
 
 namespace dom {
 
@@ -39,16 +43,17 @@ class BlobImpl;
 class BlobConstructorParams;
 class ClonedMessageData;
 class IPCTabContext;
 class PBlobChild;
 class PBrowserChild;
 
 class nsIContentChild : public nsISupports
                       , public CPOWManagerGetter
+                      , public mozilla::ipc::IShmemAllocator
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONTENTCHILD_IID)
 
   BlobChild* GetOrCreateActorForBlob(Blob* aBlob);
   BlobChild* GetOrCreateActorForBlobImpl(BlobImpl* aImpl);
 
   virtual PBlobChild*
@@ -58,16 +63,17 @@ public:
   virtual bool
   SendPBrowserConstructor(PBrowserChild* aActor,
                           const TabId& aTabId,
                           const IPCTabContext& aContext,
                           const uint32_t& aChromeFlags,
                           const ContentParentId& aCpID,
                           const bool& aIsForApp,
                           const bool& aIsForBrowser) = 0;
+
 protected:
   virtual jsipc::PJavaScriptChild* AllocPJavaScriptChild();
   virtual bool DeallocPJavaScriptChild(jsipc::PJavaScriptChild*);
 
   virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
                                             const IPCTabContext& aContext,
                                             const uint32_t& aChromeFlags,
                                             const ContentParentId& aCpId,
--- a/dom/ipc/nsIContentParent.h
+++ b/dom/ipc/nsIContentParent.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_nsIContentParent_h
 #define mozilla_dom_nsIContentParent_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/ipc/IdType.h"
+#include "mozilla/ipc/ProtocolUtils.h"
 
 #include "nsFrameMessageManager.h"
 #include "nsISupports.h"
 #include "mozilla/dom/CPOWManagerGetter.h"
 
 #define NS_ICONTENTPARENT_IID                                   \
   { 0xeeec9ebf, 0x8ecf, 0x4e38,                                 \
     { 0x81, 0xda, 0xb7, 0x34, 0x13, 0x7e, 0xac, 0xf3 } }
@@ -41,16 +42,17 @@ class ContentParent;
 class ContentBridgeParent;
 class IPCTabContext;
 class PBlobParent;
 class PBrowserParent;
 
 class nsIContentParent : public nsISupports
                        , public mozilla::dom::ipc::MessageManagerCallback
                        , public CPOWManagerGetter
+                       , public mozilla::ipc::IShmemAllocator
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONTENTPARENT_IID)
 
   nsIContentParent();
 
   BlobParent* GetOrCreateActorForBlob(Blob* aBlob);
   BlobParent* GetOrCreateActorForBlobImpl(BlobImpl* aImpl);
--- a/ipc/glue/Shmem.cpp
+++ b/ipc/glue/Shmem.cpp
@@ -20,17 +20,17 @@ class ShmemCreated : public IPC::Message
 private:
   typedef Shmem::id_t id_t;
 
 public:
   ShmemCreated(int32_t routingId,
                id_t aIPDLId,
                size_t aSize,
                SharedMemory::SharedMemoryType aType) :
-    IPC::Message(routingId, SHMEM_CREATED_MESSAGE_TYPE, PRIORITY_NORMAL)
+    IPC::Message(routingId, SHMEM_CREATED_MESSAGE_TYPE, PRIORITY_URGENT)
   {
     IPC::WriteParam(this, aIPDLId);
     IPC::WriteParam(this, aSize);
     IPC::WriteParam(this, int32_t(aType));
   }
 
   static bool
   ReadInfo(const Message* msg, PickleIterator* iter,
--- a/widget/nsClipboardProxy.cpp
+++ b/widget/nsClipboardProxy.cpp
@@ -1,13 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/ContentChild.h"
+#include "mozilla/unused.h"
 #include "nsClipboardProxy.h"
 #include "nsISupportsPrimitives.h"
 #include "nsCOMPtr.h"
 #include "nsComponentManagerUtils.h"
 #include "nsXULAppAPI.h"
 #include "nsContentUtils.h"
 #include "nsStringStream.h"
 
@@ -75,43 +76,47 @@ nsClipboardProxy::GetData(nsITransferabl
 
       nsString data = item.data().get_nsString();
       rv = dataWrapper->SetData(data);
       NS_ENSURE_SUCCESS(rv, rv);
 
       rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper,
                                           data.Length() * sizeof(char16_t));
       NS_ENSURE_SUCCESS(rv, rv);
-    } else if (item.data().type() == IPCDataTransferData::TnsCString) {
+    } else if (item.data().type() == IPCDataTransferData::TShmem) {
       // If this is an image, convert it into an nsIInputStream.
       nsCString flavor = item.flavor();
+      mozilla::ipc::Shmem data = item.data().get_Shmem();
       if (flavor.EqualsLiteral(kJPEGImageMime) ||
           flavor.EqualsLiteral(kJPGImageMime) ||
           flavor.EqualsLiteral(kPNGImageMime) ||
           flavor.EqualsLiteral(kGIFImageMime)) {
         nsCOMPtr<nsIInputStream> stream;
-        NS_NewCStringInputStream(getter_AddRefs(stream), item.data().get_nsCString());
+
+        NS_NewCStringInputStream(getter_AddRefs(stream),
+                                 nsDependentCString(data.get<char>(), data.Size<char>()));
 
         rv = aTransferable->SetTransferData(flavor.get(), stream, sizeof(nsISupports*));
         NS_ENSURE_SUCCESS(rv, rv);
       } else if (flavor.EqualsLiteral(kNativeHTMLMime) ||
                  flavor.EqualsLiteral(kRTFMime) ||
                  flavor.EqualsLiteral(kCustomTypesMime)) {
         nsCOMPtr<nsISupportsCString> dataWrapper =
           do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
         NS_ENSURE_SUCCESS(rv, rv);
 
-        nsCString data = item.data().get_nsCString();
-        rv = dataWrapper->SetData(data);
+        rv = dataWrapper->SetData(nsDependentCString(data.get<char>(), data.Size<char>()));
         NS_ENSURE_SUCCESS(rv, rv);
 
         rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper,
-                                            data.Length());
+                                            data.Size<char>());
         NS_ENSURE_SUCCESS(rv, rv);
       }
+
+      mozilla::Unused << ContentChild::GetSingleton()->DeallocShmem(data);
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsClipboardProxy::EmptyClipboard(int32_t aWhichClipboard)