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
This commit is contained in:
Jimmy Wang 2016-08-30 21:30:45 -04:00
parent 2653de86d8
commit ff4e05f90e
8 changed files with 146 additions and 55 deletions

View File

@ -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<IPCDataTransferItem>& items = aDataTransfer.items();
for (const auto& item : items) {
aTransferable->AddDataFlavor(item.flavor().get());
if (item.data().type() == IPCDataTransferData::TnsString) {
nsCOMPtr<nsISupportsString> 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<imgIContainer> imageContainer;
rv = nsContentUtils::DataTransferItemToImage(item,
getter_AddRefs(imageContainer));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupportsInterfacePointer> 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<nsISupportsCString> 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<char>(),
itemData.Size<char>());
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<IPCDataTransfer>& aIPC,

View File

@ -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<mozilla::dom::IPCDataTransfer>& aIPC,
bool aInSyncMessage,

View File

@ -2484,61 +2484,11 @@ ContentParent::RecvSetClipboard(const IPCDataTransfer& aDataTransfer,
NS_ENSURE_SUCCESS(rv, true);
trans->Init(nullptr);
const nsTArray<IPCDataTransferItem>& items = aDataTransfer.items();
for (const auto& item : items) {
trans->AddDataFlavor(item.flavor().get());
if (item.data().type() == IPCDataTransferData::TnsString) {
nsCOMPtr<nsISupportsString> 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<imgIContainer> imageContainer;
rv = nsContentUtils::DataTransferItemToImage(item,
getter_AddRefs(imageContainer));
NS_ENSURE_SUCCESS(rv, true);
nsCOMPtr<nsISupportsInterfacePointer> 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<nsISupportsCString> 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<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);
trans->SetRequestingPrincipal(aRequestingPrincipal);
rv = nsContentUtils::IPCTransferableToTransferable(aDataTransfer,
aIsPrivateData,
aRequestingPrincipal,
trans, this, nullptr);
NS_ENSURE_SUCCESS(rv, true);
clipboard->SetData(trans, nullptr, aWhichClipboard);
return true;

View File

@ -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.
*/

View File

@ -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<nsITransferable> 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<nsIDocShell> ourDocShell = do_GetInterface(WebNavigation());
if (NS_WARN_IF(!ourDocShell)) {
return true;
}
nsCOMPtr<nsICommandParams> 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&)
{

View File

@ -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;

View File

@ -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)
{

View File

@ -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);