зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1183915 - Put images dragged from content processes in the drag data in the parent. r=smaug
This commit is contained in:
Родитель
1837d54fa7
Коммит
89b19e3239
|
@ -25,7 +25,9 @@
|
|||
#include "MediaDecoder.h"
|
||||
// nsNPAPIPluginInstance must be included before nsIDocument.h, which is included in mozAutoDocUpdate.h.
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
#include "gfxDrawable.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "ImageOps.h"
|
||||
#include "mozAutoDocUpdate.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
@ -200,6 +202,7 @@
|
|||
#include "nsICookieService.h"
|
||||
#include "mozilla/EnumSet.h"
|
||||
#include "mozilla/BloomFilter.h"
|
||||
#include "SourceSurfaceRawData.h"
|
||||
|
||||
#include "nsIBidiKeyboard.h"
|
||||
|
||||
|
@ -216,6 +219,7 @@ extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end,
|
|||
class imgLoader;
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::widget;
|
||||
using namespace mozilla;
|
||||
|
@ -7427,6 +7431,48 @@ nsContentUtils::IsFileImage(nsIFile* aFile, nsACString& aType)
|
|||
return StringBeginsWith(aType, NS_LITERAL_CSTRING("image/"));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsContentUtils::DataTransferItemToImage(const IPCDataTransferItem& aItem,
|
||||
imgIContainer** aContainer)
|
||||
{
|
||||
MOZ_ASSERT(aItem.data().type() == IPCDataTransferData::TnsCString);
|
||||
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();
|
||||
|
||||
// InitWrappingData takes a non-const pointer for reading.
|
||||
nsCString& nonConstText = const_cast<nsCString&>(text);
|
||||
RefPtr<SourceSurfaceRawData> image = new SourceSurfaceRawData();
|
||||
image->InitWrappingData(reinterpret_cast<uint8_t*>(nonConstText.BeginWriting()),
|
||||
size, imageDetails.stride(),
|
||||
static_cast<SurfaceFormat>(imageDetails.format()),
|
||||
false);
|
||||
image->GuaranteePersistance();
|
||||
|
||||
RefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(image, size);
|
||||
nsCOMPtr<imgIContainer> imageContainer =
|
||||
image::ImageOps::CreateFromDrawable(drawable);
|
||||
imageContainer.forget(aContainer);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::IsFlavorImage(const nsACString& aFlavor)
|
||||
{
|
||||
return aFlavor.EqualsLiteral(kNativeImageMime) ||
|
||||
aFlavor.EqualsLiteral(kJPEGImageMime) ||
|
||||
aFlavor.EqualsLiteral(kJPGImageMime) ||
|
||||
aFlavor.EqualsLiteral(kPNGImageMime) ||
|
||||
aFlavor.EqualsLiteral(kGIFImageMime);
|
||||
}
|
||||
|
||||
void
|
||||
nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
|
||||
IPCDataTransfer* aIPCDataTransfer,
|
||||
|
|
|
@ -121,6 +121,7 @@ class DocumentFragment;
|
|||
class Element;
|
||||
class EventTarget;
|
||||
class IPCDataTransfer;
|
||||
class IPCDataTransferItem;
|
||||
class NodeInfo;
|
||||
class nsIContentChild;
|
||||
class nsIContentParent;
|
||||
|
@ -2428,6 +2429,21 @@ public:
|
|||
*/
|
||||
static bool IsFileImage(nsIFile* aFile, nsACString& aType);
|
||||
|
||||
/**
|
||||
* Given an IPCDataTransferItem that has a flavor for which IsFlavorImage
|
||||
* returns true and whose IPCDataTransferData is of type nsCString (raw image
|
||||
* data), construct an imgIContainer for the image encoded by the transfer
|
||||
* item.
|
||||
*/
|
||||
static nsresult DataTransferItemToImage(const mozilla::dom::IPCDataTransferItem& aItem,
|
||||
imgIContainer** aContainer);
|
||||
|
||||
/**
|
||||
* Given a flavor obtained from an IPCDataTransferItem or nsITransferable,
|
||||
* returns true if we should treat the data as an image.
|
||||
*/
|
||||
static bool IsFlavorImage(const nsACString& aFlavor);
|
||||
|
||||
static void TransferablesToIPCTransferables(nsISupportsArray* aTransferables,
|
||||
nsTArray<mozilla::dom::IPCDataTransfer>& aIPC,
|
||||
bool aInSyncMessage,
|
||||
|
|
|
@ -156,8 +156,6 @@
|
|||
#include "nsPIWindowWatcher.h"
|
||||
#include "nsWindowWatcher.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "gfxDrawable.h"
|
||||
#include "ImageOps.h"
|
||||
#include "mozilla/dom/nsMixedContentBlocker.h"
|
||||
#include "nsMemoryInfoDumper.h"
|
||||
#include "nsMemoryReporterManager.h"
|
||||
|
@ -2865,75 +2863,56 @@ ContentParent::RecvSetClipboard(const IPCDataTransfer& aDataTransfer,
|
|||
nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
|
||||
nsCOMPtr<nsITransferable> trans =
|
||||
do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
trans->Init(nullptr);
|
||||
|
||||
const nsTArray<IPCDataTransferItem>& items = aDataTransfer.items();
|
||||
for (uint32_t j = 0; j < items.Length(); ++j) {
|
||||
const IPCDataTransferItem& item = items[j];
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
if (item.flavor().EqualsLiteral(kNativeImageMime) ||
|
||||
item.flavor().EqualsLiteral(kJPEGImageMime) ||
|
||||
item.flavor().EqualsLiteral(kJPGImageMime) ||
|
||||
item.flavor().EqualsLiteral(kPNGImageMime) ||
|
||||
item.flavor().EqualsLiteral(kGIFImageMime)) {
|
||||
const IPCDataTransferImage& imageDetails = item.imageDetails();
|
||||
const gfx::IntSize size(imageDetails.width(), imageDetails.height());
|
||||
if (!size.width || !size.height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCString text = item.data().get_nsCString();
|
||||
RefPtr<gfx::DataSourceSurface> image =
|
||||
new mozilla::gfx::SourceSurfaceRawData();
|
||||
mozilla::gfx::SourceSurfaceRawData* raw =
|
||||
static_cast<mozilla::gfx::SourceSurfaceRawData*>(image.get());
|
||||
raw->InitWrappingData(
|
||||
reinterpret_cast<uint8_t*>(const_cast<nsCString&>(text).BeginWriting()),
|
||||
size, imageDetails.stride(),
|
||||
static_cast<mozilla::gfx::SurfaceFormat>(imageDetails.format()), false);
|
||||
raw->GuaranteePersistance();
|
||||
|
||||
RefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(image, size);
|
||||
nsCOMPtr<imgIContainer> imageContainer(image::ImageOps::CreateFromDrawable(drawable));
|
||||
|
||||
nsCOMPtr<nsISupportsInterfacePointer>
|
||||
imgPtr(do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv));
|
||||
|
||||
rv = imgPtr->SetData(imageContainer);
|
||||
nsCOMPtr<nsISupportsString> dataWrapper =
|
||||
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
|
||||
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();
|
||||
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());
|
||||
rv = trans->SetTransferData(item.flavor().get(), dataWrapper,
|
||||
text.Length() * sizeof(char16_t));
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
}
|
||||
} else if (item.data().type() == IPCDataTransferData::TnsCString) {
|
||||
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);
|
||||
|
||||
const nsCString& text = item.data().get_nsCString();
|
||||
rv = dataWrapper->SetData(text);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
rv = trans->SetTransferData(item.flavor().get(), dataWrapper, text.Length());
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3152,24 +3152,7 @@ TabParent::RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
|
|||
|
||||
EventStateManager* esm = shell->GetPresContext()->EventStateManager();
|
||||
for (uint32_t i = 0; i < aTransfers.Length(); ++i) {
|
||||
auto& items = aTransfers[i].items();
|
||||
nsTArray<DataTransferItem>* itemArray = mInitialDataTransferItems.AppendElement();
|
||||
for (uint32_t j = 0; j < items.Length(); ++j) {
|
||||
const IPCDataTransferItem& item = items[j];
|
||||
DataTransferItem* localItem = itemArray->AppendElement();
|
||||
localItem->mFlavor = item.flavor();
|
||||
if (item.data().type() == IPCDataTransferData::TnsString) {
|
||||
localItem->mType = DataTransferItem::DataType::eString;
|
||||
localItem->mStringData = item.data().get_nsString();
|
||||
} else if (item.data().type() == IPCDataTransferData::TPBlobChild) {
|
||||
localItem->mType = DataTransferItem::DataType::eBlob;
|
||||
BlobParent* blobParent =
|
||||
static_cast<BlobParent*>(item.data().get_PBlobParent());
|
||||
if (blobParent) {
|
||||
localItem->mBlobData = blobParent->GetBlobImpl();
|
||||
}
|
||||
}
|
||||
}
|
||||
mInitialDataTransferItems.AppendElement(mozilla::Move(aTransfers[i].items()));
|
||||
}
|
||||
if (Manager()->IsContentParent()) {
|
||||
nsCOMPtr<nsIDragService> dragService =
|
||||
|
@ -3205,24 +3188,37 @@ void
|
|||
TabParent::AddInitialDnDDataTo(DataTransfer* aDataTransfer)
|
||||
{
|
||||
for (uint32_t i = 0; i < mInitialDataTransferItems.Length(); ++i) {
|
||||
nsTArray<DataTransferItem>& itemArray = mInitialDataTransferItems[i];
|
||||
for (uint32_t j = 0; j < itemArray.Length(); ++j) {
|
||||
DataTransferItem& item = itemArray[j];
|
||||
nsTArray<IPCDataTransferItem>& itemArray = mInitialDataTransferItems[i];
|
||||
for (auto& item : itemArray) {
|
||||
RefPtr<nsVariantCC> variant = new nsVariantCC();
|
||||
// Special case kFilePromiseMime so that we get the right
|
||||
// nsIFlavorDataProvider for it.
|
||||
if (item.mFlavor.EqualsLiteral(kFilePromiseMime)) {
|
||||
if (item.flavor().EqualsLiteral(kFilePromiseMime)) {
|
||||
RefPtr<nsISupports> flavorDataProvider =
|
||||
new nsContentAreaDragDropDataProvider();
|
||||
variant->SetAsISupports(flavorDataProvider);
|
||||
} else if (item.mType == DataTransferItem::DataType::eString) {
|
||||
variant->SetAsAString(item.mStringData);
|
||||
} else if (item.mType == DataTransferItem::DataType::eBlob) {
|
||||
variant->SetAsISupports(item.mBlobData);
|
||||
} 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 &&
|
||||
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);
|
||||
}
|
||||
|
||||
// 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->SetDataWithPrincipal(NS_ConvertUTF8toUTF16(item.mFlavor),
|
||||
aDataTransfer->SetDataWithPrincipal(NS_ConvertUTF8toUTF16(item.flavor()),
|
||||
variant, i,
|
||||
nsContentUtils::GetSystemPrincipal());
|
||||
}
|
||||
|
|
|
@ -644,19 +644,7 @@ private:
|
|||
|
||||
uint32_t mChromeFlags;
|
||||
|
||||
struct DataTransferItem
|
||||
{
|
||||
nsCString mFlavor;
|
||||
nsString mStringData;
|
||||
RefPtr<mozilla::dom::BlobImpl> mBlobData;
|
||||
enum DataType
|
||||
{
|
||||
eString,
|
||||
eBlob
|
||||
};
|
||||
DataType mType;
|
||||
};
|
||||
nsTArray<nsTArray<DataTransferItem>> mInitialDataTransferItems;
|
||||
nsTArray<nsTArray<IPCDataTransferItem>> mInitialDataTransferItems;
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> mDnDVisualization;
|
||||
int32_t mDragAreaX;
|
||||
|
|
Загрузка…
Ссылка в новой задаче