Additional changes needed to fix bug 280947 (dragging of images whose extension doesn't map to the right mimetype on the client is broken). r=bzbarsky@mit.edu, sr=dveditz@cruzio.com

This commit is contained in:
jst%mozilla.jstenback.com 2005-02-18 19:18:20 +00:00
Родитель 4d1d6f1b06
Коммит b7bbeee847
3 изменённых файлов: 86 добавлений и 75 удалений

Просмотреть файл

@ -151,6 +151,7 @@ private:
nsString mUrlString;
nsString mImageSourceString;
nsString mImageDestFileName;
nsString mTitleString;
nsString mHtmlString; // will be filled automatically if you fill urlstring
nsString mContextString;
@ -716,60 +717,28 @@ nsContentAreaDragDrop::HandleEvent(nsIDOMEvent *event)
// used on platforms where it's possible to drag items (e.g. images)
// into the file system
nsresult
nsContentAreaDragDrop::SaveURIToFileInDirectory(nsAString& inSourceURIString, nsILocalFile* inDestDirectory, nsILocalFile** outFile)
nsContentAreaDragDrop::SaveURIToFile(nsAString& inSourceURIString,
nsIFile* inDestFile)
{
*outFile = nsnull;
nsresult rv;
// clone it because it belongs to the drag data, so we shouldn't mess with it
nsCOMPtr<nsIFile> clonedFile;
rv = inDestDirectory->Clone(getter_AddRefs(clonedFile));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsILocalFile> destFile = do_QueryInterface(clonedFile);
if (!destFile) return NS_ERROR_NO_INTERFACE;
nsCOMPtr<nsIURI> sourceURI;
rv = NS_NewURI(getter_AddRefs(sourceURI), inSourceURIString);
nsresult rv = NS_NewURI(getter_AddRefs(sourceURI), inSourceURIString);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsCOMPtr<nsIURL> sourceURL = do_QueryInterface(sourceURI);
if (!sourceURL) return NS_ERROR_NO_INTERFACE;
nsCAutoString fileName; // escaped, UTF-8
sourceURL->GetFileName(fileName);
rv = inDestFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
NS_ENSURE_SUCCESS(rv, rv);
if (fileName.IsEmpty())
return NS_ERROR_FAILURE; // this is an error; the URL must point to a file
NS_UnescapeURL(fileName);
NS_ConvertUTF8toUCS2 wideFileName(fileName);
// make the name safe for the filesystem
wideFileName.ReplaceChar(PRUnichar('/'), PRUnichar('_'));
wideFileName.ReplaceChar(PRUnichar('\\'), PRUnichar('_'));
wideFileName.ReplaceChar(PRUnichar(':'), PRUnichar('_'));
rv = destFile->Append(wideFileName);
if (NS_FAILED(rv)) return rv;
rv = destFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
if (NS_FAILED(rv)) return rv;
// we rely on the fact that the WPB is refcounted by the channel etc,
// so we don't keep a ref to it. It will die when finished.
nsCOMPtr<nsIWebBrowserPersist> persist = do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1", &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIWebBrowserPersist> persist =
do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1",
&rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupports> fileAsSupports = do_QueryInterface(destFile);
rv = persist->SaveURI(sourceURI, nsnull, nsnull, nsnull, nsnull, fileAsSupports);
if (NS_FAILED(rv)) return rv;
*outFile = destFile;
NS_ADDREF(*outFile);
return NS_OK;
return persist->SaveURI(sourceURI, nsnull, nsnull, nsnull, nsnull,
inDestFile);
}
// This is our nsIFlavorDataProvider callback. There are several assumptions here that
@ -797,33 +766,54 @@ nsContentAreaDragDrop::GetFlavorData(nsITransferable *aTransferable,
{
// get the URI from the kFilePromiseURLMime flavor
NS_ENSURE_ARG(aTransferable);
nsCOMPtr<nsISupports> urlPrimitive;
nsCOMPtr<nsISupports> tmp;
PRUint32 dataSize = 0;
aTransferable->GetTransferData(kFilePromiseURLMime, getter_AddRefs(urlPrimitive), &dataSize);
nsCOMPtr<nsISupportsString> srcUrlPrimitive = do_QueryInterface(urlPrimitive);
if (!srcUrlPrimitive) return NS_ERROR_FAILURE;
aTransferable->GetTransferData(kFilePromiseURLMime,
getter_AddRefs(tmp), &dataSize);
nsCOMPtr<nsISupportsString> supportsString =
do_QueryInterface(tmp);
if (!supportsString)
return NS_ERROR_FAILURE;
nsAutoString sourceURLString;
srcUrlPrimitive->GetData(sourceURLString);
supportsString->GetData(sourceURLString);
if (sourceURLString.IsEmpty())
return NS_ERROR_FAILURE;
aTransferable->GetTransferData(kFilePromiseDestFilename,
getter_AddRefs(tmp), &dataSize);
supportsString = do_QueryInterface(tmp);
if (!supportsString)
return NS_ERROR_FAILURE;
nsAutoString targetFilename;
supportsString->GetData(targetFilename);
if (targetFilename.IsEmpty())
return NS_ERROR_FAILURE;
// get the target directory from the kFilePromiseDirectoryMime flavor
nsCOMPtr<nsISupports> dirPrimitive;
dataSize = 0;
aTransferable->GetTransferData(kFilePromiseDirectoryMime, getter_AddRefs(dirPrimitive), &dataSize);
aTransferable->GetTransferData(kFilePromiseDirectoryMime,
getter_AddRefs(dirPrimitive), &dataSize);
nsCOMPtr<nsILocalFile> destDirectory = do_QueryInterface(dirPrimitive);
if (!destDirectory) return NS_ERROR_FAILURE;
if (!destDirectory)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIFile> file;
rv = destDirectory->Clone(getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv, rv);
file->Append(targetFilename);
// now save the file
nsCOMPtr<nsILocalFile> destFile;
rv = SaveURIToFileInDirectory(sourceURLString, destDirectory, getter_AddRefs(destFile));
rv = SaveURIToFile(sourceURLString, file);
// send back an nsILocalFile
if (NS_SUCCEEDED(rv))
{
CallQueryInterface(destFile, aData);
*aDataLen = sizeof(nsILocalFile*);
CallQueryInterface(file, aData);
*aDataLen = sizeof(nsIFile*);
}
}
@ -1136,27 +1126,39 @@ nsTransferableFactory::Produce(nsITransferable** outTrans)
getter_AddRefs(mimeInfo));
if (mimeInfo) {
PRBool validExtension;
if (NS_FAILED(mimeInfo->ExtensionExists(extension,
&validExtension)) ||
!validExtension) {
nsresult rv = imgUrl->Clone(getter_AddRefs(imgUri));
NS_ENSURE_SUCCESS(rv, rv);
imgUrl = do_QueryInterface(imgUri);
mimeInfo->GetPrimaryExtension(extension);
imgUrl->SetFileExtension(extension);
}
nsCAutoString spec;
imgUrl->GetSpec(spec);
// pass out the image source string
CopyUTF8toUTF16(spec, mImageSourceString);
PRBool validExtension;
if (NS_FAILED(mimeInfo->ExtensionExists(extension,
&validExtension)) ||
!validExtension) {
// Fix the file extension in the URL
nsresult rv = imgUrl->Clone(getter_AddRefs(imgUri));
NS_ENSURE_SUCCESS(rv, rv);
imgUrl = do_QueryInterface(imgUri);
nsCAutoString primaryExtension;
mimeInfo->GetPrimaryExtension(primaryExtension);
imgUrl->SetFileExtension(primaryExtension);
}
nsCAutoString fileName;
imgUrl->GetFileName(fileName);
NS_UnescapeURL(fileName);
// make the filename safe for the filesystem
fileName.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS,
'-');
CopyUTF8toUTF16(fileName, mImageDestFileName);
// and the image object
mImage = img;
}
@ -1310,7 +1312,7 @@ nsTransferableFactory::ConvertStringsToTransferable(nsITransferable** outTrans)
if ( !ptrPrimitive )
return NS_ERROR_FAILURE;
ptrPrimitive->SetData(mImage);
trans->SetTransferData(kNativeImageMime, ptrPrimitive, sizeof(nsIImage*));
trans->SetTransferData(kNativeImageMime, ptrPrimitive, sizeof(nsISupportsInterfacePointer*));
// assume the image comes from a file, and add a file promise. We register ourselves
// as a nsIFlavorDataProvider, and will use the GetFlavorData callback to save the
// image to disk.
@ -1322,6 +1324,12 @@ nsTransferableFactory::ConvertStringsToTransferable(nsITransferable** outTrans)
imageUrlPrimitive->SetData(mImageSourceString);
trans->SetTransferData(kFilePromiseURLMime, imageUrlPrimitive, mImageSourceString.Length() * sizeof(PRUnichar));
nsCOMPtr<nsISupportsString> imageFileNamePrimitive(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
if (!imageFileNamePrimitive)
return NS_ERROR_FAILURE;
imageFileNamePrimitive->SetData(mImageDestFileName);
trans->SetTransferData(kFilePromiseDestFilename, imageFileNamePrimitive, mImageDestFileName.Length() * sizeof(PRUnichar));
// if not an anchor, add the image url
if (!mIsAnchor)
{

Просмотреть файл

@ -56,7 +56,7 @@ class nsPresContext;
class nsIContent;
class nsIDocument;
class nsIURI;
class nsILocalFile;
class nsIFile;
class nsISimpleEnumerator;
// {1f34bc80-1bc7-11d6-a384-d705dd0746fc}
@ -103,7 +103,8 @@ private:
static void NormalizeSelection(nsIDOMNode* inBaseNode, nsISelection* inSelection);
static void GetEventDocument(nsIDOMEvent* inEvent, nsIDOMDocument** outDocument);
static nsresult SaveURIToFileInDirectory(nsAString& inSourceURIString, nsILocalFile* inDestDirectory, nsILocalFile** outFile);
static nsresult SaveURIToFile(nsAString& inSourceURIString,
nsIFile* inDestFile);
nsresult CreateTransferable(nsIDOMEvent* inMouseEvent, nsITransferable** outTrans);
void ExtractURLFromData(const nsACString & inFlavor, nsISupports* inDataWrapper, PRUint32 inDataLen,

Просмотреть файл

@ -63,6 +63,8 @@
// the source URL for a file promise
#define kFilePromiseURLMime "application/x-moz-file-promise-url"
// the destination filename for a file promise
#define kFilePromiseDestFilename "application/x-moz-file-promise-dest-filename"
// a dataless flavor used to interact with the OS during file drags
#define kFilePromiseMime "application/x-moz-file-promise"
// a synthetic flavor, put into the transferable once we know the destination directory of a file drag