void DataTransfer::CacheExternalData(const char* aFormat, uint32_t aIndex, nsIPrincipal* aPrincipal) { if (strcmp(aFormat, kUnicodeMime) == 0) { SetDataWithPrincipal(NS_LITERAL_STRING("text/plain"), nullptr, aIndex, aPrincipal); } else { if (strcmp(aFormat, kURLDataMime) == 0) { SetDataWithPrincipal(NS_LITERAL_STRING("text/uri-list"), nullptr, aIndex, aPrincipal); } SetDataWithPrincipal(NS_ConvertUTF8toUTF16(aFormat), nullptr, aIndex, aPrincipal); } }
void nsDOMDataTransfer::CacheExternalFormats() { // Called during the constructor to cache the formats available from an // external drag. The data associated with each format will be set to null. // This data will instead only be retrieved in FillInExternalDragData when // asked for, as it may be time consuming for the source application to // generate it. nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession(); if (!dragSession) return; // make sure that the system principal is used for external drags nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); nsCOMPtr<nsIPrincipal> sysPrincipal; ssm->GetSystemPrincipal(getter_AddRefs(sysPrincipal)); // there isn't a way to get a list of the formats that might be available on // all platforms, so just check for the types that can actually be imported // XXXndeakin there are some other formats but those are platform specific. const char* formats[] = { kFileMime, kHTMLMime, kURLMime, kURLDataMime, kUnicodeMime }; PRUint32 count; dragSession->GetNumDropItems(&count); for (PRUint32 c = 0; c < count; c++) { for (PRUint32 f = 0; f < NS_ARRAY_LENGTH(formats); f++) { // IsDataFlavorSupported doesn't take an index as an argument and just // checks if any of the items support a particular flavor, even though // the GetData method does take an index. Here, we just assume that // every item being dragged has the same set of flavors. PRBool supported; dragSession->IsDataFlavorSupported(formats[f], &supported); // if the format is supported, add an item to the array with null as // the data. When retrieved, GetRealData will read the data. if (supported) { if (strcmp(formats[f], kUnicodeMime) == 0) { SetDataWithPrincipal(NS_LITERAL_STRING("text/plain"), nsnull, c, sysPrincipal); } else { if (strcmp(formats[f], kURLDataMime) == 0) SetDataWithPrincipal(NS_LITERAL_STRING("text/uri-list"), nsnull, c, sysPrincipal); SetDataWithPrincipal(NS_ConvertUTF8toUTF16(formats[f]), nsnull, c, sysPrincipal); } } } } }
NS_IMETHODIMP DataTransfer::MozSetDataAt(const nsAString& aFormat, nsIVariant* aData, uint32_t aIndex) { if (aFormat.IsEmpty()) { return NS_OK; } if (mReadOnly) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } // Specifying an index less than the current length will replace an existing // item. Specifying an index equal to the current length will add a new item. if (aIndex > mItems.Length()) { return NS_ERROR_DOM_INDEX_SIZE_ERR; } // Only the first item is valid for clipboard events if (aIndex > 0 && (mEventType == NS_CUT || mEventType == NS_COPY || mEventType == NS_PASTE)) { return NS_ERROR_DOM_INDEX_SIZE_ERR; } // don't allow non-chrome to add file data // XXX perhaps this should also limit any non-string type as well if ((aFormat.EqualsLiteral("application/x-moz-file-promise") || aFormat.EqualsLiteral("application/x-moz-file")) && !nsContentUtils::IsCallerChrome()) { return NS_ERROR_DOM_SECURITY_ERR; } return SetDataWithPrincipal(aFormat, aData, aIndex, nsContentUtils::SubjectPrincipal()); }
DataTransferItem* DataTransferItemList::Add(File& aData, nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) { if (mDataTransfer->IsReadOnly()) { return nullptr; } nsCOMPtr<nsISupports> supports = do_QueryObject(&aData); nsCOMPtr<nsIWritableVariant> data = new nsVariantCC(); data->SetAsISupports(supports); nsAutoString type; aData.GetType(type); if (!DataTransfer::PrincipalMaySetData(type, data, &aSubjectPrincipal)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return nullptr; } // We need to add this as a new item, as multiple files can't exist in the // same item in the Moz DataTransfer layout. It will be appended at the end of // the internal specced layout. uint32_t index = mIndexedItems.Length(); RefPtr<DataTransferItem> item = SetDataWithPrincipal(type, data, index, &aSubjectPrincipal, /* aInsertOnly = */ true, /* aHidden = */ false, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } MOZ_ASSERT(item->Kind() == DataTransferItem::KIND_FILE); return item; }
DataTransferItem* DataTransferItemList::Add(const nsAString& aData, const nsAString& aType, nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) { if (NS_WARN_IF(mDataTransfer->IsReadOnly())) { return nullptr; } RefPtr<nsVariantCC> data(new nsVariantCC()); data->SetAsAString(aData); nsAutoString format; mDataTransfer->GetRealFormat(aType, format); if (!DataTransfer::PrincipalMaySetData(format, data, &aSubjectPrincipal)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return nullptr; } // We add the textual data to index 0. We set aInsertOnly to true, as we don't // want to update an existing entry if it is already present, as per the spec. RefPtr<DataTransferItem> item = SetDataWithPrincipal(format, data, 0, &aSubjectPrincipal, /* aInsertOnly = */ true, /* aHidden = */ false, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } MOZ_ASSERT(item->Kind() != DataTransferItem::KIND_FILE); return item; }
NS_IMETHODIMP nsDOMDataTransfer::MozSetDataAt(const nsAString& aFormat, nsIVariant* aData, PRUint32 aIndex) { NS_ENSURE_TRUE(aData, NS_ERROR_NULL_POINTER); if (aFormat.IsEmpty()) return NS_OK; if (mReadOnly) return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; // Specifying an index less than the current length will replace an existing // item. Specifying an index equal to the current length will add a new item. if (aIndex > mItems.Length()) return NS_ERROR_DOM_INDEX_SIZE_ERR; // don't allow non-chrome to add file data // XXX perhaps this should also limit any non-string type as well if ((aFormat.EqualsLiteral("application/x-moz-file-promise") || aFormat.EqualsLiteral("application/x-moz-file")) && !nsContentUtils::IsCallerTrustedForCapability("UniversalXPConnect")) { return NS_ERROR_DOM_SECURITY_ERR; } nsresult rv = NS_OK; nsIPrincipal* principal = GetCurrentPrincipal(&rv); NS_ENSURE_SUCCESS(rv, rv); return SetDataWithPrincipal(aFormat, aData, aIndex, principal); }
void DataTransfer::FillInExternalCustomTypes(nsIVariant* aData, uint32_t aIndex, nsIPrincipal* aPrincipal) { char* chrs; uint32_t len = 0; nsresult rv = aData->GetAsStringWithSize(&len, &chrs); if (NS_FAILED(rv)) { return; } nsAutoCString str; str.Adopt(chrs, len); nsCOMPtr<nsIInputStream> stringStream; NS_NewCStringInputStream(getter_AddRefs(stringStream), str); nsCOMPtr<nsIBinaryInputStream> stream = do_CreateInstance("@mozilla.org/binaryinputstream;1"); if (!stream) { return; } rv = stream->SetInputStream(stringStream); NS_ENSURE_SUCCESS_VOID(rv); uint32_t type; do { rv = stream->Read32(&type); NS_ENSURE_SUCCESS_VOID(rv); if (type == eCustomClipboardTypeId_String) { uint32_t formatLength; rv = stream->Read32(&formatLength); NS_ENSURE_SUCCESS_VOID(rv); char* formatBytes; rv = stream->ReadBytes(formatLength, &formatBytes); NS_ENSURE_SUCCESS_VOID(rv); nsAutoString format; format.Adopt(reinterpret_cast<char16_t*>(formatBytes), formatLength / sizeof(char16_t)); uint32_t dataLength; rv = stream->Read32(&dataLength); NS_ENSURE_SUCCESS_VOID(rv); char* dataBytes; rv = stream->ReadBytes(dataLength, &dataBytes); NS_ENSURE_SUCCESS_VOID(rv); nsAutoString data; data.Adopt(reinterpret_cast<char16_t*>(dataBytes), dataLength / sizeof(char16_t)); RefPtr<nsVariantCC> variant = new nsVariantCC(); rv = variant->SetAsAString(data); NS_ENSURE_SUCCESS_VOID(rv); SetDataWithPrincipal(format, variant, aIndex, aPrincipal); } } while (type != eCustomClipboardTypeId_None); }
void DataTransfer::FillInExternalCustomTypes(nsIVariant* aData, uint32_t aIndex, nsIPrincipal* aPrincipal) { char* chrs; uint32_t len = 0; nsresult rv = aData->GetAsStringWithSize(&len, &chrs); if (NS_FAILED(rv)) { return; } CheckedInt<int32_t> checkedLen(len); if (!checkedLen.isValid()) { return; } nsCOMPtr<nsIInputStream> stringStream; NS_NewByteInputStream(getter_AddRefs(stringStream), chrs, checkedLen.value(), NS_ASSIGNMENT_ADOPT); nsCOMPtr<nsIObjectInputStream> stream = NS_NewObjectInputStream(stringStream); uint32_t type; do { rv = stream->Read32(&type); NS_ENSURE_SUCCESS_VOID(rv); if (type == eCustomClipboardTypeId_String) { uint32_t formatLength; rv = stream->Read32(&formatLength); NS_ENSURE_SUCCESS_VOID(rv); char* formatBytes; rv = stream->ReadBytes(formatLength, &formatBytes); NS_ENSURE_SUCCESS_VOID(rv); nsAutoString format; format.Adopt(reinterpret_cast<char16_t*>(formatBytes), formatLength / sizeof(char16_t)); uint32_t dataLength; rv = stream->Read32(&dataLength); NS_ENSURE_SUCCESS_VOID(rv); char* dataBytes; rv = stream->ReadBytes(dataLength, &dataBytes); NS_ENSURE_SUCCESS_VOID(rv); nsAutoString data; data.Adopt(reinterpret_cast<char16_t*>(dataBytes), dataLength / sizeof(char16_t)); RefPtr<nsVariantCC> variant = new nsVariantCC(); rv = variant->SetAsAString(data); NS_ENSURE_SUCCESS_VOID(rv); SetDataWithPrincipal(format, variant, aIndex, aPrincipal); } } while (type != eCustomClipboardTypeId_None); }
void DataTransfer::SetDataWithPrincipalFromOtherProcess(const nsAString& aFormat, nsIVariant* aData, uint32_t aIndex, nsIPrincipal* aPrincipal) { if (aFormat.EqualsLiteral(kCustomTypesMime)) { FillInExternalCustomTypes(aData, aIndex, aPrincipal); } else { SetDataWithPrincipal(aFormat, aData, aIndex, aPrincipal); } }
nsresult DataTransfer::SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData, uint32_t aIndex, nsIPrincipal* aSubjectPrincipal) { if (aFormat.IsEmpty()) { return NS_OK; } if (mReadOnly) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } // Specifying an index less than the current length will replace an existing // item. Specifying an index equal to the current length will add a new item. if (aIndex > mItems.Length()) { return NS_ERROR_DOM_INDEX_SIZE_ERR; } // Only the first item is valid for clipboard events if (aIndex > 0 && (mEventMessage == eCut || mEventMessage == eCopy || mEventMessage == ePaste)) { return NS_ERROR_DOM_INDEX_SIZE_ERR; } // Don't allow the custom type to be assigned. if (aFormat.EqualsLiteral(kCustomTypesMime)) { return NS_ERROR_TYPE_ERR; } // Don't allow non-chrome to add non-string or file data. We'll block file // promises as well which are used internally for drags to the desktop. if (!nsContentUtils::IsSystemPrincipal(aSubjectPrincipal)) { if (aFormat.EqualsLiteral(kFilePromiseMime) || aFormat.EqualsLiteral(kFileMime)) { return NS_ERROR_DOM_SECURITY_ERR; } uint16_t type; aData->GetDataType(&type); if (type == nsIDataType::VTYPE_INTERFACE || type == nsIDataType::VTYPE_INTERFACE_IS) { return NS_ERROR_DOM_SECURITY_ERR; } } return SetDataWithPrincipal(aFormat, aData, aIndex, aSubjectPrincipal); }
nsresult DataTransfer::SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData, uint32_t aIndex, nsIPrincipal* aSubjectPrincipal) { if (aFormat.IsEmpty()) { return NS_OK; } if (mReadOnly) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } // Specifying an index less than the current length will replace an existing // item. Specifying an index equal to the current length will add a new item. if (aIndex > MozItemCount()) { return NS_ERROR_DOM_INDEX_SIZE_ERR; } // Only the first item is valid for clipboard events if (aIndex > 0 && (mEventMessage == eCut || mEventMessage == eCopy || mEventMessage == ePaste)) { return NS_ERROR_DOM_INDEX_SIZE_ERR; } // Don't allow the custom type to be assigned. if (aFormat.EqualsLiteral(kCustomTypesMime)) { return NS_ERROR_TYPE_ERR; } if (!PrincipalMaySetData(aFormat, aData, aSubjectPrincipal)) { return NS_ERROR_DOM_SECURITY_ERR; } return SetDataWithPrincipal(aFormat, aData, aIndex, aSubjectPrincipal); }