Follow up patch to bug 183582.

This was requested in order to get sr= for the previous checkin.
I'm checking this in as a separate step, to make the real
logic change easier recognizable.

This checkin does not change any logic.
It only moves methods around in the file.

sr=sfraser


git-svn-id: svn://10.0.0.236/trunk@143820 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
kaie%netscape.com
2003-06-17 22:35:01 +00:00
parent f502e06fe5
commit fe47815320

View File

@@ -120,6 +120,51 @@ NS_INTERFACE_MAP_BEGIN(nsContentAreaDragDrop)
NS_INTERFACE_MAP_END
class nsTransferableFactory
{
public:
static nsresult CreateFromEvent(nsIDOMEvent* inMouseEvent, nsIFlavorDataProvider *inFlavorDataProvider,
nsITransferable** outTrans);
protected:
nsTransferableFactory(nsIDOMEvent* inMouseEvent, nsIFlavorDataProvider *inFlavorDataProvider);
nsresult Produce(nsITransferable** outTrans);
private:
nsresult ConvertStringsToTransferable(nsITransferable** outTrans);
static nsresult GetDraggableSelectionData(nsISelection* inSelection, nsIDOMNode* inRealTargetNode,
nsIDOMNode **outImageOrLinkNode, PRBool* outDragSelectedText);
static void FindParentLinkNode(nsIDOMNode* inNode, nsIDOMNode** outParent);
static void GetAnchorURL(nsIDOMNode* inNode, nsAString& outURL);
static void GetNodeString(nsIDOMNode* inNode, nsAString & outNodeString);
static nsresult GetImageFromDOMNode(nsIDOMNode* inNode, nsIImage** outImage);
static void CreateLinkText(const nsAString& inURL, const nsAString & inText,
nsAString& outLinkText);
static void FindFirstAnchor(nsIDOMNode* inNode, nsIDOMNode** outAnchor);
enum serializationMode {serializeAsText, serializeAsHTML};
// if inNode is null, use the selection from the window
static nsresult SerializeNodeOrSelection(serializationMode inMode, PRUint32 inFlags,
nsIDOMWindow* inWindow, nsIDOMNode* inNode, nsAString& outResultString,
nsAString& outHTMLContext, nsAString& outHTMLInfo);
PRBool mInstanceAlreadyUsed;
nsCOMPtr<nsIDOMEvent> mMouseEvent;
nsCOMPtr<nsIFlavorDataProvider> mFlavorDataProvider;
nsString mUrlString;
nsString mImageSourceString;
nsString mTitleString;
nsString mHtmlString; // will be filled automatically if you fill urlstring
nsString mContextString;
nsString mInfoString;
PRBool mIsAnchor;
nsCOMPtr<nsIImage> mImage;
};
//
// nsContentAreaDragDrop ctor
//
@@ -435,49 +480,316 @@ nsContentAreaDragDrop::DragDrop(nsIDOMEvent* inMouseEvent)
return NS_OK;
}
class nsTransferableFactory
//
// NormalizeSelection
//
void
nsContentAreaDragDrop::NormalizeSelection(nsIDOMNode* inBaseNode, nsISelection* inSelection)
{
public:
static nsresult CreateFromEvent(nsIDOMEvent* inMouseEvent, nsIFlavorDataProvider *inFlavorDataProvider,
nsITransferable** outTrans);
nsCOMPtr<nsIDOMNode> parent;
inBaseNode->GetParentNode(getter_AddRefs(parent));
if ( !parent || !inSelection )
return;
protected:
nsTransferableFactory(nsIDOMEvent* inMouseEvent, nsIFlavorDataProvider *inFlavorDataProvider);
nsresult Produce(nsITransferable** outTrans);
nsCOMPtr<nsIDOMNodeList> childNodes;
parent->GetChildNodes(getter_AddRefs(childNodes));
if ( !childNodes )
return;
PRUint32 listLen = 0;
childNodes->GetLength(&listLen);
PRUint32 index = 0;
for ( ; index < listLen; ++index ) {
nsCOMPtr<nsIDOMNode> indexedNode;
childNodes->Item(index, getter_AddRefs(indexedNode));
if ( indexedNode == inBaseNode )
break;
}
if ( index >= listLen )
return;
// now make the selection contain all of |inBaseNode|'s siblings up to and including
// |inBaseNode|
inSelection->Collapse(parent, index);
inSelection->Extend(parent, index+1);
}
private:
nsresult ConvertStringsToTransferable(nsITransferable** outTrans);
static nsresult GetDraggableSelectionData(nsISelection* inSelection, nsIDOMNode* inRealTargetNode,
nsIDOMNode **outImageOrLinkNode, PRBool* outDragSelectedText);
static void FindParentLinkNode(nsIDOMNode* inNode, nsIDOMNode** outParent);
static void GetAnchorURL(nsIDOMNode* inNode, nsAString& outURL);
static void GetNodeString(nsIDOMNode* inNode, nsAString & outNodeString);
static nsresult GetImageFromDOMNode(nsIDOMNode* inNode, nsIImage** outImage);
static void CreateLinkText(const nsAString& inURL, const nsAString & inText,
nsAString& outLinkText);
static void FindFirstAnchor(nsIDOMNode* inNode, nsIDOMNode** outAnchor);
enum serializationMode {serializeAsText, serializeAsHTML};
// if inNode is null, use the selection from the window
static nsresult SerializeNodeOrSelection(serializationMode inMode, PRUint32 inFlags,
nsIDOMWindow* inWindow, nsIDOMNode* inNode, nsAString& outResultString,
nsAString& outHTMLContext, nsAString& outHTMLInfo);
//
// GetEventDocument
//
// Get the DOM document associated with a given DOM event
//
void
nsContentAreaDragDrop::GetEventDocument(nsIDOMEvent* inEvent, nsIDOMDocument** outDocument)
{
if ( !outDocument )
return;
*outDocument = nsnull;
nsCOMPtr<nsIDOMUIEvent> uiEvent(do_QueryInterface(inEvent));
if ( uiEvent ) {
nsCOMPtr<nsIDOMAbstractView> view;
uiEvent->GetView(getter_AddRefs(view));
nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(view));
if ( window )
window->GetDocument(outDocument);
}
}
PRBool mInstanceAlreadyUsed;
nsresult
nsContentAreaDragDrop::CreateTransferable(nsIDOMEvent* inMouseEvent, nsITransferable** outTrans)
{
return nsTransferableFactory::CreateFromEvent(inMouseEvent,
NS_STATIC_CAST(nsIFlavorDataProvider*, this),
outTrans);
}
nsCOMPtr<nsIDOMEvent> mMouseEvent;
nsCOMPtr<nsIFlavorDataProvider> mFlavorDataProvider;
nsresult
nsContentAreaDragDrop::GetHookEnumeratorFromEvent(nsIDOMEvent* inEvent,
nsISimpleEnumerator **outEnumerator)
{
*outEnumerator = nsnull;
nsString mUrlString;
nsString mImageSourceString;
nsString mTitleString;
nsString mHtmlString; // will be filled automatically if you fill urlstring
nsString mContextString;
nsString mInfoString;
nsCOMPtr<nsIDOMDocument> domdoc;
GetEventDocument(inEvent, getter_AddRefs(domdoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
nsCOMPtr<nsISupports> isupp;
doc->GetContainer(getter_AddRefs(isupp));
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(isupp);
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
nsCOMPtr<nsIClipboardDragDropHookList> hookList = do_GetInterface(docShell);
NS_ENSURE_TRUE(hookList, NS_ERROR_FAILURE);
nsCOMPtr<nsISimpleEnumerator> enumerator;
hookList->GetHookEnumerator(getter_AddRefs(enumerator));
NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
*outEnumerator = enumerator;
NS_ADDREF(*outEnumerator);
return NS_OK;
}
//
// DragGesture
//
// Determine if the user has started to drag something and kick off
// an OS-level drag if it's applicable
//
NS_IMETHODIMP
nsContentAreaDragDrop::DragGesture(nsIDOMEvent* inMouseEvent)
{
// first check that someone hasn't already handled this event
PRBool preventDefault = PR_TRUE;
nsCOMPtr<nsIDOMNSUIEvent> nsuiEvent(do_QueryInterface(inMouseEvent));
if ( nsuiEvent )
nsuiEvent->GetPreventDefault(&preventDefault);
if ( preventDefault )
return NS_OK;
// if the client has provided an override callback, check if we
// should continue
nsCOMPtr<nsISimpleEnumerator> enumerator;
GetHookEnumeratorFromEvent(inMouseEvent, getter_AddRefs(enumerator));
if (enumerator) {
PRBool allow = PR_TRUE;
PRBool hasMoreHooks = PR_FALSE;
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
&& hasMoreHooks) {
nsCOMPtr<nsISupports> isupp;
if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp))))
break;
nsCOMPtr<nsIClipboardDragDropHooks> override = do_QueryInterface(isupp);
if (override) {
nsresult hookResult = override->AllowStartDrag(inMouseEvent, &allow);
NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in AllowStartDrag");
if (!allow)
return NS_OK;
}
}
}
nsCOMPtr<nsITransferable> trans;
nsresult rv = CreateTransferable(inMouseEvent, getter_AddRefs(trans));
if (NS_FAILED(rv))
return rv;
if ( trans ) {
// if the client has provided an override callback, let them manipulate
// the flavors or drag data
nsCOMPtr<nsISimpleEnumerator> enumerator;
GetHookEnumeratorFromEvent(inMouseEvent, getter_AddRefs(enumerator));
if (enumerator)
{
PRBool hasMoreHooks = PR_FALSE;
PRBool doContinueDrag = PR_TRUE;
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
&& hasMoreHooks)
{
nsCOMPtr<nsISupports> isupp;
if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp))))
break;
nsCOMPtr<nsIClipboardDragDropHooks> override = do_QueryInterface(isupp);
if (override)
{
nsresult hookResult = override->OnCopyOrDrag(inMouseEvent, trans, &doContinueDrag);
NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnCopyOrDrag");
if (!doContinueDrag)
return NS_OK;
}
}
}
nsCOMPtr<nsISupportsArray> transArray(do_CreateInstance("@mozilla.org/supports-array;1"));
if ( !transArray )
return NS_ERROR_FAILURE;
transArray->InsertElementAt(trans, 0);
// kick off the drag
nsCOMPtr<nsIDOMEventTarget> target;
inMouseEvent->GetTarget(getter_AddRefs(target));
nsCOMPtr<nsIDOMNode> targetNode(do_QueryInterface(target));
nsCOMPtr<nsIDragService> dragService(do_GetService("@mozilla.org/widget/dragservice;1"));
if ( !dragService )
return NS_ERROR_FAILURE;
dragService->InvokeDragSession(targetNode, transArray, nsnull, nsIDragService::DRAGDROP_ACTION_COPY +
nsIDragService::DRAGDROP_ACTION_MOVE + nsIDragService::DRAGDROP_ACTION_LINK);
}
return NS_OK;
}
NS_IMETHODIMP
nsContentAreaDragDrop::HandleEvent(nsIDOMEvent *event)
{
return NS_OK;
}
#if 0
#pragma mark -
#endif
// SaveURIToFile
// 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)
{
*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);
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);
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<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;
}
// This is our nsIFlavorDataProvider callback. There are several assumptions here that
// make this work:
//
// 1. Someone put a kFilePromiseURLMime flavor into the transferable with the source
// URI of the file to save (as a string). We did that above.
//
// 2. Someone put a kFilePromiseDirectoryMime flavor into the transferable with
// an nsILocalFile for the directory we are to save in. That has to be done
// by platform-specific code (in widget), which gets the destination directory
// from OS-specific drag information.
//
NS_IMETHODIMP
nsContentAreaDragDrop::GetFlavorData(nsITransferable *aTransferable,
const char *aFlavor, nsISupports **aData, PRUint32 *aDataLen)
{
NS_ENSURE_ARG_POINTER(aData && aDataLen);
*aData = nsnull;
*aDataLen = 0;
nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
if (strcmp(aFlavor, kFilePromiseMime) == 0)
{
// get the URI from the kFilePromiseURLMime flavor
NS_ENSURE_ARG(aTransferable);
nsCOMPtr<nsISupports> urlPrimitive;
PRUint32 dataSize = 0;
aTransferable->GetTransferData(kFilePromiseURLMime, getter_AddRefs(urlPrimitive), &dataSize);
nsCOMPtr<nsISupportsString> srcUrlPrimitive = do_QueryInterface(urlPrimitive);
if (!srcUrlPrimitive) return NS_ERROR_FAILURE;
nsAutoString sourceURLString;
srcUrlPrimitive->GetData(sourceURLString);
if (sourceURLString.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);
nsCOMPtr<nsILocalFile> destDirectory = do_QueryInterface(dirPrimitive);
if (!destDirectory) return NS_ERROR_FAILURE;
// now save the file
nsCOMPtr<nsILocalFile> destFile;
rv = SaveURIToFileInDirectory(sourceURLString, destDirectory, getter_AddRefs(destFile));
// send back an nsILocalFile
if (NS_SUCCEEDED(rv))
{
CallQueryInterface(destFile, aData);
*aDataLen = sizeof(nsILocalFile*);
}
}
return rv;
}
PRBool mIsAnchor;
nsCOMPtr<nsIImage> mImage;
};
nsresult
nsTransferableFactory::CreateFromEvent(nsIDOMEvent* inMouseEvent, nsIFlavorDataProvider *inFlavorDataProvider,
@@ -743,62 +1055,6 @@ nsTransferableFactory::GetNodeString(nsIDOMNode* inNode, nsAString & outNodeStri
}
//
// NormalizeSelection
//
void
nsContentAreaDragDrop::NormalizeSelection(nsIDOMNode* inBaseNode, nsISelection* inSelection)
{
nsCOMPtr<nsIDOMNode> parent;
inBaseNode->GetParentNode(getter_AddRefs(parent));
if ( !parent || !inSelection )
return;
nsCOMPtr<nsIDOMNodeList> childNodes;
parent->GetChildNodes(getter_AddRefs(childNodes));
if ( !childNodes )
return;
PRUint32 listLen = 0;
childNodes->GetLength(&listLen);
PRUint32 index = 0;
for ( ; index < listLen; ++index ) {
nsCOMPtr<nsIDOMNode> indexedNode;
childNodes->Item(index, getter_AddRefs(indexedNode));
if ( indexedNode == inBaseNode )
break;
}
if ( index >= listLen )
return;
// now make the selection contain all of |inBaseNode|'s siblings up to and including
// |inBaseNode|
inSelection->Collapse(parent, index);
inSelection->Extend(parent, index+1);
}
//
// GetEventDocument
//
// Get the DOM document associated with a given DOM event
//
void
nsContentAreaDragDrop::GetEventDocument(nsIDOMEvent* inEvent, nsIDOMDocument** outDocument)
{
if ( !outDocument )
return;
*outDocument = nsnull;
nsCOMPtr<nsIDOMUIEvent> uiEvent(do_QueryInterface(inEvent));
if ( uiEvent ) {
nsCOMPtr<nsIDOMAbstractView> view;
uiEvent->GetView(getter_AddRefs(view));
nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(view));
if ( window )
window->GetDocument(outDocument);
}
}
nsresult
nsTransferableFactory::Produce(nsITransferable** outTrans)
{
@@ -1123,138 +1379,6 @@ nsTransferableFactory::ConvertStringsToTransferable(nsITransferable** outTrans)
return NS_OK;
}
nsresult
nsContentAreaDragDrop::CreateTransferable(nsIDOMEvent* inMouseEvent, nsITransferable** outTrans)
{
return nsTransferableFactory::CreateFromEvent(inMouseEvent,
NS_STATIC_CAST(nsIFlavorDataProvider*, this),
outTrans);
}
nsresult
nsContentAreaDragDrop::GetHookEnumeratorFromEvent(nsIDOMEvent* inEvent,
nsISimpleEnumerator **outEnumerator)
{
*outEnumerator = nsnull;
nsCOMPtr<nsIDOMDocument> domdoc;
GetEventDocument(inEvent, getter_AddRefs(domdoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
nsCOMPtr<nsISupports> isupp;
doc->GetContainer(getter_AddRefs(isupp));
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(isupp);
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
nsCOMPtr<nsIClipboardDragDropHookList> hookList = do_GetInterface(docShell);
NS_ENSURE_TRUE(hookList, NS_ERROR_FAILURE);
nsCOMPtr<nsISimpleEnumerator> enumerator;
hookList->GetHookEnumerator(getter_AddRefs(enumerator));
NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
*outEnumerator = enumerator;
NS_ADDREF(*outEnumerator);
return NS_OK;
}
//
// DragGesture
//
// Determine if the user has started to drag something and kick off
// an OS-level drag if it's applicable
//
NS_IMETHODIMP
nsContentAreaDragDrop::DragGesture(nsIDOMEvent* inMouseEvent)
{
// first check that someone hasn't already handled this event
PRBool preventDefault = PR_TRUE;
nsCOMPtr<nsIDOMNSUIEvent> nsuiEvent(do_QueryInterface(inMouseEvent));
if ( nsuiEvent )
nsuiEvent->GetPreventDefault(&preventDefault);
if ( preventDefault )
return NS_OK;
// if the client has provided an override callback, check if we
// should continue
nsCOMPtr<nsISimpleEnumerator> enumerator;
GetHookEnumeratorFromEvent(inMouseEvent, getter_AddRefs(enumerator));
if (enumerator) {
PRBool allow = PR_TRUE;
PRBool hasMoreHooks = PR_FALSE;
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
&& hasMoreHooks) {
nsCOMPtr<nsISupports> isupp;
if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp))))
break;
nsCOMPtr<nsIClipboardDragDropHooks> override = do_QueryInterface(isupp);
if (override) {
nsresult hookResult = override->AllowStartDrag(inMouseEvent, &allow);
NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in AllowStartDrag");
if (!allow)
return NS_OK;
}
}
}
nsCOMPtr<nsITransferable> trans;
nsresult rv = CreateTransferable(inMouseEvent, getter_AddRefs(trans));
if (NS_FAILED(rv))
return rv;
if ( trans ) {
// if the client has provided an override callback, let them manipulate
// the flavors or drag data
nsCOMPtr<nsISimpleEnumerator> enumerator;
GetHookEnumeratorFromEvent(inMouseEvent, getter_AddRefs(enumerator));
if (enumerator)
{
PRBool hasMoreHooks = PR_FALSE;
PRBool doContinueDrag = PR_TRUE;
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks))
&& hasMoreHooks)
{
nsCOMPtr<nsISupports> isupp;
if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp))))
break;
nsCOMPtr<nsIClipboardDragDropHooks> override = do_QueryInterface(isupp);
if (override)
{
nsresult hookResult = override->OnCopyOrDrag(inMouseEvent, trans, &doContinueDrag);
NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnCopyOrDrag");
if (!doContinueDrag)
return NS_OK;
}
}
}
nsCOMPtr<nsISupportsArray> transArray(do_CreateInstance("@mozilla.org/supports-array;1"));
if ( !transArray )
return NS_ERROR_FAILURE;
transArray->InsertElementAt(trans, 0);
// kick off the drag
nsCOMPtr<nsIDOMEventTarget> target;
inMouseEvent->GetTarget(getter_AddRefs(target));
nsCOMPtr<nsIDOMNode> targetNode(do_QueryInterface(target));
nsCOMPtr<nsIDragService> dragService(do_GetService("@mozilla.org/widget/dragservice;1"));
if ( !dragService )
return NS_ERROR_FAILURE;
dragService->InvokeDragSession(targetNode, transArray, nsnull, nsIDragService::DRAGDROP_ACTION_COPY +
nsIDragService::DRAGDROP_ACTION_MOVE + nsIDragService::DRAGDROP_ACTION_LINK);
}
return NS_OK;
}
NS_IMETHODIMP
nsContentAreaDragDrop::HandleEvent(nsIDOMEvent *event)
{
return NS_OK;
}
// static
// note that this can return NS_OK, but a null out param (by design)
nsresult nsTransferableFactory::GetDraggableSelectionData(nsISelection* inSelection,
@@ -1455,126 +1579,3 @@ nsTransferableFactory::GetImageFromDOMNode(nsIDOMNode* inNode, nsIImage**outImag
return CallGetInterface(ir.get(), outImage);
}
#if 0
#pragma mark -
#endif
// SaveURIToFile
// 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)
{
*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);
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);
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<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;
}
// This is our nsIFlavorDataProvider callback. There are several assumptions here that
// make this work:
//
// 1. Someone put a kFilePromiseURLMime flavor into the transferable with the source
// URI of the file to save (as a string). We did that above.
//
// 2. Someone put a kFilePromiseDirectoryMime flavor into the transferable with
// an nsILocalFile for the directory we are to save in. That has to be done
// by platform-specific code (in widget), which gets the destination directory
// from OS-specific drag information.
//
NS_IMETHODIMP
nsContentAreaDragDrop::GetFlavorData(nsITransferable *aTransferable,
const char *aFlavor, nsISupports **aData, PRUint32 *aDataLen)
{
NS_ENSURE_ARG_POINTER(aData && aDataLen);
*aData = nsnull;
*aDataLen = 0;
nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
if (strcmp(aFlavor, kFilePromiseMime) == 0)
{
// get the URI from the kFilePromiseURLMime flavor
NS_ENSURE_ARG(aTransferable);
nsCOMPtr<nsISupports> urlPrimitive;
PRUint32 dataSize = 0;
aTransferable->GetTransferData(kFilePromiseURLMime, getter_AddRefs(urlPrimitive), &dataSize);
nsCOMPtr<nsISupportsString> srcUrlPrimitive = do_QueryInterface(urlPrimitive);
if (!srcUrlPrimitive) return NS_ERROR_FAILURE;
nsAutoString sourceURLString;
srcUrlPrimitive->GetData(sourceURLString);
if (sourceURLString.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);
nsCOMPtr<nsILocalFile> destDirectory = do_QueryInterface(dirPrimitive);
if (!destDirectory) return NS_ERROR_FAILURE;
// now save the file
nsCOMPtr<nsILocalFile> destFile;
rv = SaveURIToFileInDirectory(sourceURLString, destDirectory, getter_AddRefs(destFile));
// send back an nsILocalFile
if (NS_SUCCEEDED(rv))
{
CallQueryInterface(destFile, aData);
*aDataLen = sizeof(nsILocalFile*);
}
}
return rv;
}