From ff4e05f90e59082fb3aebfc6fabac34a205c7adc Mon Sep 17 00:00:00 2001 From: Jimmy Wang Date: Tue, 30 Aug 2016 21:30:45 -0400 Subject: [PATCH] Bug 1297539 - Add IPC message, PasteTransferable, to call PasteTransferable via a controller on the content process to handle the command content event, "pasteTransferable". New method nsContentUtils::IPCTransferableToTransferable since ContentParent::RecvSetClipboard and TabChild::RecvPasteTransferable both require the same setup to make a transferable. r=mrbkap MozReview-Commit-ID: 3I443eBOPEO --HG-- extra : rebase_source : 86dbafb500c68e9a1f9976a6016d4e42311a4de8 --- dom/base/nsContentUtils.cpp | 72 +++++++++++++++++++++++++++++++++++++ dom/base/nsContentUtils.h | 8 +++++ dom/ipc/ContentParent.cpp | 60 +++---------------------------- dom/ipc/PBrowser.ipdl | 8 +++++ dom/ipc/TabChild.cpp | 34 ++++++++++++++++++ dom/ipc/TabChild.h | 5 +++ dom/ipc/TabParent.cpp | 10 ++++++ dom/ipc/TabParent.h | 4 +++ 8 files changed, 146 insertions(+), 55 deletions(-) diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 98f3dbb7eb9c..f13a016761e2 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -7393,6 +7393,78 @@ nsContentUtils::SetKeyboardIndicatorsOnRemoteChildren(nsPIDOMWindowOuter* aWindo (void *)&stateInfo); } +nsresult +nsContentUtils::IPCTransferableToTransferable(const IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, + nsIPrincipal* aRequestingPrincipal, + nsITransferable* aTransferable, + mozilla::dom::nsIContentParent* aContentParent, + mozilla::dom::TabChild* aTabChild) +{ + nsresult rv; + + const nsTArray& items = aDataTransfer.items(); + for (const auto& item : items) { + aTransferable->AddDataFlavor(item.flavor().get()); + + if (item.data().type() == IPCDataTransferData::TnsString) { + nsCOMPtr dataWrapper = + do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + const nsString& text = item.data().get_nsString(); + rv = dataWrapper->SetData(text); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper, + text.Length() * sizeof(char16_t)); + + NS_ENSURE_SUCCESS(rv, rv); + } else if (item.data().type() == IPCDataTransferData::TShmem) { + if (nsContentUtils::IsFlavorImage(item.flavor())) { + nsCOMPtr imageContainer; + rv = nsContentUtils::DataTransferItemToImage(item, + getter_AddRefs(imageContainer)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr imgPtr = + do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID); + NS_ENSURE_TRUE(imgPtr, NS_ERROR_FAILURE); + + rv = imgPtr->SetData(imageContainer); + NS_ENSURE_SUCCESS(rv, rv); + + aTransferable->SetTransferData(item.flavor().get(), imgPtr, sizeof(nsISupports*)); + } else { + nsCOMPtr dataWrapper = + do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + // The buffer contains the terminating null. + Shmem itemData = item.data().get_Shmem(); + const nsDependentCString text(itemData.get(), + itemData.Size()); + rv = dataWrapper->SetData(text); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aTransferable->SetTransferData(item.flavor().get(), dataWrapper, text.Length()); + + NS_ENSURE_SUCCESS(rv, rv); + } + + if (aContentParent) { + Unused << aContentParent->DeallocShmem(item.data().get_Shmem()); + } else if (aTabChild) { + Unused << aTabChild->DeallocShmem(item.data().get_Shmem()); + } + } + } + + aTransferable->SetIsPrivateData(aIsPrivateData); + aTransferable->SetRequestingPrincipal(aRequestingPrincipal); + return NS_OK; +} + void nsContentUtils::TransferablesToIPCTransferables(nsISupportsArray* aTransferables, nsTArray& aIPC, diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index d66b3dd06af1..fcba794ab658 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -127,6 +127,7 @@ class IPCDataTransferItem; class NodeInfo; class nsIContentChild; class nsIContentParent; +class TabChild; class Selection; class TabParent; } // namespace dom @@ -2481,6 +2482,13 @@ public: */ static bool IsFlavorImage(const nsACString& aFlavor); + static nsresult IPCTransferableToTransferable(const mozilla::dom::IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, + nsIPrincipal* aRequestingPrincipal, + nsITransferable* aTransferable, + mozilla::dom::nsIContentParent* aContentParent, + mozilla::dom::TabChild* aTabChild); + static void TransferablesToIPCTransferables(nsISupportsArray* aTransferables, nsTArray& aIPC, bool aInSyncMessage, diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 52088461f0cb..201c16adc164 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -2484,61 +2484,11 @@ ContentParent::RecvSetClipboard(const IPCDataTransfer& aDataTransfer, NS_ENSURE_SUCCESS(rv, true); trans->Init(nullptr); - const nsTArray& items = aDataTransfer.items(); - for (const auto& item : items) { - trans->AddDataFlavor(item.flavor().get()); - - if (item.data().type() == IPCDataTransferData::TnsString) { - nsCOMPtr dataWrapper = - do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, true); - - 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::TShmem) { - if (nsContentUtils::IsFlavorImage(item.flavor())) { - nsCOMPtr imageContainer; - rv = nsContentUtils::DataTransferItemToImage(item, - getter_AddRefs(imageContainer)); - NS_ENSURE_SUCCESS(rv, true); - - nsCOMPtr imgPtr = - do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID); - NS_ENSURE_TRUE(imgPtr, true); - - rv = imgPtr->SetData(imageContainer); - NS_ENSURE_SUCCESS(rv, true); - - trans->SetTransferData(item.flavor().get(), imgPtr, sizeof(nsISupports*)); - } else { - nsCOMPtr dataWrapper = - do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, true); - - // The buffer contains the terminating null. - Shmem itemData = item.data().get_Shmem(); - const nsDependentCString text(itemData.get(), - itemData.Size()); - 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); - trans->SetRequestingPrincipal(aRequestingPrincipal); + rv = nsContentUtils::IPCTransferableToTransferable(aDataTransfer, + aIsPrivateData, + aRequestingPrincipal, + trans, this, nullptr); + NS_ENSURE_SUCCESS(rv, true); clipboard->SetData(trans, nullptr, aWhichClipboard); return true; diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 446a9a1b4165..3b4b78428c64 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -674,6 +674,14 @@ child: async SelectionEvent(WidgetSelectionEvent event); + /** + * Call PasteTransferable via a controller on the content process + * to handle the command content event, "pasteTransferable". + */ + async PasteTransferable(IPCDataTransfer aDataTransfer, + bool aIsPrivateData, + Principal aRequestingPrincipal); + /** * Activate event forwarding from client to parent. */ diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 98338f1ff20a..8d3ae9427ae0 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -112,6 +112,7 @@ #include "nsSandboxFlags.h" #include "FrameLayerBuilder.h" #include "VRManagerChild.h" +#include "nsICommandParams.h" #ifdef NS_PRINTING #include "nsIPrintSession.h" @@ -2146,6 +2147,39 @@ TabChild::RecvSelectionEvent(const WidgetSelectionEvent& event) return true; } +bool +TabChild::RecvPasteTransferable(const IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, + const IPC::Principal& aRequestingPrincipal) +{ + nsresult rv; + nsCOMPtr trans = + do_CreateInstance("@mozilla.org/widget/transferable;1", &rv); + NS_ENSURE_SUCCESS(rv, true); + trans->Init(nullptr); + + rv = nsContentUtils::IPCTransferableToTransferable(aDataTransfer, + aIsPrivateData, + aRequestingPrincipal, + trans, nullptr, this); + NS_ENSURE_SUCCESS(rv, true); + + nsCOMPtr ourDocShell = do_GetInterface(WebNavigation()); + if (NS_WARN_IF(!ourDocShell)) { + return true; + } + + nsCOMPtr params = do_CreateInstance("@mozilla.org/embedcomp/command-params;1", &rv); + NS_ENSURE_SUCCESS(rv, true); + + rv = params->SetISupportsValue("transferable", trans); + NS_ENSURE_SUCCESS(rv, true); + + ourDocShell->DoCommandWithParams("cmd_pasteTransferable", params); + return true; +} + + a11y::PDocAccessibleChild* TabChild::AllocPDocAccessibleChild(PDocAccessibleChild*, const uint64_t&) { diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index aaa71b84bbab..7c97e30fb409 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -399,6 +399,11 @@ public: virtual bool RecvSelectionEvent(const mozilla::WidgetSelectionEvent& aEvent) override; + virtual bool + RecvPasteTransferable(const IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, + const IPC::Principal& aRequestingPrincipal) override; + virtual bool RecvActivateFrameEvent(const nsString& aType, const bool& aCapture) override; diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index b55f67372377..2774ca97ff4c 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -2226,6 +2226,16 @@ TabParent::SendSelectionEvent(WidgetSelectionEvent& event) return true; } +bool +TabParent::SendPasteTransferable(const IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, + const IPC::Principal& aRequestingPrincipal) +{ + return PBrowserParent::SendPasteTransferable(aDataTransfer, + aIsPrivateData, + aRequestingPrincipal); +} + /*static*/ TabParent* TabParent::GetFrom(nsFrameLoader* aFrameLoader) { diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index acef93dbe463..950171cdc16b 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -540,6 +540,10 @@ public: bool SendSelectionEvent(mozilla::WidgetSelectionEvent& event); + bool SendPasteTransferable(const IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, + const IPC::Principal& aRequestingPrincipal); + static TabParent* GetFrom(nsFrameLoader* aFrameLoader); static TabParent* GetFrom(nsIFrameLoader* aFrameLoader);