зеркало из https://github.com/mozilla/gecko-dev.git
Bug 854299 - Part 1. Split nsExternalAppHandler::SaveToDisk in two parts to make second part async. r=bz sr=roc
This commit is contained in:
Родитель
d71be8c99e
Коммит
91d91d3c58
|
@ -189,6 +189,10 @@ nsUnknownContentTypeDialog.prototype = {
|
|||
// Note - this function is called without a dialog, so it cannot access any part
|
||||
// of the dialog XUL as other functions on this object do.
|
||||
promptForSaveToFile: function(aLauncher, aContext, aDefaultFile, aSuggestedFileExtension, aForcePrompt) {
|
||||
throw new Components.Exception("Async version must be used", Components.results.NS_ERROR_NOT_AVAILABLE);
|
||||
},
|
||||
|
||||
promptForSaveToFileAsync: function(aLauncher, aContext, aDefaultFile, aSuggestedFileExtension, aForcePrompt) {
|
||||
var result = null;
|
||||
|
||||
this.mLauncher = aLauncher;
|
||||
|
@ -226,13 +230,16 @@ nsUnknownContentTypeDialog.prototype = {
|
|||
bundle.GetStringFromName("badPermissions.title"),
|
||||
bundle.GetStringFromName("badPermissions"));
|
||||
|
||||
aLauncher.saveDestinationAvailable(null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check to make sure we have a valid directory, otherwise, prompt
|
||||
if (result)
|
||||
return result;
|
||||
if (result) {
|
||||
aLauncher.saveDestinationAvailable(result);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,7 +290,8 @@ nsUnknownContentTypeDialog.prototype = {
|
|||
|
||||
if (picker.show() == nsIFilePicker.returnCancel) {
|
||||
// null result means user cancelled.
|
||||
return null;
|
||||
aLauncher.saveDestinationAvailable(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Be sure to save the directory the user chose through the Save As...
|
||||
|
@ -307,7 +315,8 @@ nsUnknownContentTypeDialog.prototype = {
|
|||
|
||||
result = this.validateLeafName(newDir, result.leafName, null);
|
||||
}
|
||||
return result;
|
||||
aLauncher.saveDestinationAvailable(result);
|
||||
return;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -1994,7 +1994,17 @@ nsresult nsExternalAppHandler::CreateProgressListener()
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsExternalAppHandler::PromptForSaveToFile(nsIFile ** aNewFile, const nsAFlatString &aDefaultFile, const nsAFlatString &aFileExtension)
|
||||
nsresult nsExternalAppHandler::SaveDestinationAvailable(nsIFile * aFile)
|
||||
{
|
||||
if (aFile)
|
||||
ContinueSave(aFile);
|
||||
else
|
||||
Cancel(NS_BINDING_ABORTED);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsExternalAppHandler::RequestSaveDestination(const nsAFlatString &aDefaultFile, const nsAFlatString &aFileExtension)
|
||||
{
|
||||
// invoke the dialog!!!!! use mWindowContext as the window context parameter for the dialog request
|
||||
// Convert to use file picker? No, then embeddors could not do any sort of
|
||||
|
@ -2004,7 +2014,10 @@ nsresult nsExternalAppHandler::PromptForSaveToFile(nsIFile ** aNewFile, const ns
|
|||
{
|
||||
// Get helper app launcher dialog.
|
||||
mDialog = do_CreateInstance( NS_HELPERAPPLAUNCHERDLG_CONTRACTID, &rv );
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (rv != NS_OK) {
|
||||
Cancel(NS_BINDING_ABORTED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// we want to explicitly unescape aDefaultFile b4 passing into the dialog. we can't unescape
|
||||
|
@ -2015,14 +2028,25 @@ nsresult nsExternalAppHandler::PromptForSaveToFile(nsIFile ** aNewFile, const ns
|
|||
// picker is up would cause Cancel() to be called, and the dialog would be
|
||||
// released, which would release this object too, which would crash.
|
||||
// See Bug 249143
|
||||
nsIFile* fileToUse;
|
||||
nsRefPtr<nsExternalAppHandler> kungFuDeathGrip(this);
|
||||
nsCOMPtr<nsIHelperAppLauncherDialog> dlg(mDialog);
|
||||
rv = mDialog->PromptForSaveToFile(this,
|
||||
rv = mDialog->PromptForSaveToFile(this,
|
||||
mWindowContext,
|
||||
aDefaultFile.get(),
|
||||
aFileExtension.get(),
|
||||
mForceSave, aNewFile);
|
||||
return rv;
|
||||
mForceSave, &fileToUse);
|
||||
|
||||
if (rv == NS_ERROR_NOT_AVAILABLE) {
|
||||
// we need to use the async version -> nsIHelperAppLauncherDialog.promptForSaveToFileAsync.
|
||||
rv = mDialog->PromptForSaveToFileAsync(this,
|
||||
mWindowContext,
|
||||
aDefaultFile.get(),
|
||||
aFileExtension.get(),
|
||||
mForceSave);
|
||||
} else {
|
||||
SaveDestinationAvailable(rv == NS_OK ? fileToUse : nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsExternalAppHandler::MoveFile(nsIFile * aNewFileLocation)
|
||||
|
@ -2089,7 +2113,6 @@ nsresult nsExternalAppHandler::MoveFile(nsIFile * aNewFileLocation)
|
|||
|
||||
NS_IMETHODIMP nsExternalAppHandler::SaveToDisk(nsIFile * aNewFileLocation, bool aRememberThisPreference)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (mCanceled)
|
||||
return NS_OK;
|
||||
|
||||
|
@ -2098,11 +2121,9 @@ NS_IMETHODIMP nsExternalAppHandler::SaveToDisk(nsIFile * aNewFileLocation, bool
|
|||
// The helper app dialog has told us what to do.
|
||||
mReceivedDispositionInfo = true;
|
||||
|
||||
nsCOMPtr<nsIFile> fileToUse = do_QueryInterface(aNewFileLocation);
|
||||
if (!fileToUse)
|
||||
{
|
||||
if (!aNewFileLocation) {
|
||||
if (mSuggestedFileName.IsEmpty())
|
||||
rv = PromptForSaveToFile(getter_AddRefs(fileToUse), mTempLeafName, mTempFileExtension);
|
||||
RequestSaveDestination(mTempLeafName, mTempFileExtension);
|
||||
else
|
||||
{
|
||||
nsAutoString fileExt;
|
||||
|
@ -2112,15 +2133,20 @@ NS_IMETHODIMP nsExternalAppHandler::SaveToDisk(nsIFile * aNewFileLocation, bool
|
|||
if (fileExt.IsEmpty())
|
||||
fileExt = mTempFileExtension;
|
||||
|
||||
rv = PromptForSaveToFile(getter_AddRefs(fileToUse), mSuggestedFileName, fileExt);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv) || !fileToUse) {
|
||||
Cancel(NS_BINDING_ABORTED);
|
||||
return NS_ERROR_FAILURE;
|
||||
RequestSaveDestination(mSuggestedFileName, fileExt);
|
||||
}
|
||||
} else {
|
||||
ContinueSave(aNewFileLocation);
|
||||
}
|
||||
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult nsExternalAppHandler::ContinueSave(nsIFile * aNewFileLocation)
|
||||
{
|
||||
NS_PRECONDITION(aNewFileLocation, "Must be called with a non-null file");
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIFile> fileToUse = do_QueryInterface(aNewFileLocation);
|
||||
mFinalFileDestination = do_QueryInterface(fileToUse);
|
||||
|
||||
// Move what we have in the final directory, but append .part
|
||||
|
|
|
@ -342,9 +342,34 @@ protected:
|
|||
* what's going on...
|
||||
*/
|
||||
nsresult CreateProgressListener();
|
||||
nsresult PromptForSaveToFile(nsIFile ** aNewFile,
|
||||
const nsAFlatString &aDefaultFile,
|
||||
const nsAFlatString &aDefaultFileExt);
|
||||
|
||||
|
||||
/*
|
||||
* The following two functions are part of the split of SaveToDisk
|
||||
* to make it async, and works as following:
|
||||
*
|
||||
* SaveToDisk -------> RequestSaveDestination
|
||||
* .
|
||||
* .
|
||||
* v
|
||||
* ContinueSave <------- SaveDestinationAvailable
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is called by SaveToDisk to decide what's the final
|
||||
* file destination chosen by the user or by auto-download settings.
|
||||
*/
|
||||
void RequestSaveDestination(const nsAFlatString &aDefaultFile,
|
||||
const nsAFlatString &aDefaultFileExt);
|
||||
|
||||
/**
|
||||
* When SaveToDisk is called, it possibly delegates to RequestSaveDestination
|
||||
* to decide the file destination. ContinueSave must then be called when
|
||||
* the final destination is finally known.
|
||||
* @param aFile The file that was chosen as the final destination.
|
||||
* Must not be null.
|
||||
*/
|
||||
nsresult ContinueSave(nsIFile* aFile);
|
||||
|
||||
/**
|
||||
* After we're done prompting the user for any information, if the original
|
||||
|
|
|
@ -76,7 +76,7 @@ interface nsPIExternalAppLauncher : nsISupports
|
|||
* Note that cancelling the load via the nsICancelable interface will release
|
||||
* the reference to the launcher dialog.
|
||||
*/
|
||||
[scriptable, uuid(d9a19faf-497b-408c-b995-777d956b72c0)]
|
||||
[scriptable, uuid(acf2a516-7d7f-4771-8b22-6c4a559c088e)]
|
||||
interface nsIHelperAppLauncher : nsICancelable
|
||||
{
|
||||
/**
|
||||
|
@ -110,6 +110,13 @@ interface nsIHelperAppLauncher : nsICancelable
|
|||
*/
|
||||
void launchWithApplication(in nsIFile aApplication, in boolean aRememberThisPreference);
|
||||
|
||||
/**
|
||||
* Callback invoked by nsIHelperAppLauncherDialog::promptForSaveToFileAsync
|
||||
* after the user has chosen a file through the File Picker (or dismissed it).
|
||||
* @param aFile The file that was chosen by the user (or null if dialog was dismissed).
|
||||
*/
|
||||
void saveDestinationAvailable(in nsIFile aFile);
|
||||
|
||||
/**
|
||||
* The following methods are used by the progress dialog to get or set
|
||||
* information on the current helper app launcher download.
|
||||
|
|
|
@ -21,7 +21,7 @@ interface nsIFile;
|
|||
* will access methods of the nsIHelperAppLauncher passed in to show()
|
||||
* in order to cause a "save to disk" or "open using" action.
|
||||
*/
|
||||
[scriptable, uuid(f3704fdc-8ae6-4eba-a3c3-f02958ac0649)]
|
||||
[scriptable, uuid(3ae4dca8-ac91-4891-adcf-3fbebed6170e)]
|
||||
interface nsIHelperAppLauncherDialog : nsISupports {
|
||||
/**
|
||||
* This request is passed to the helper app dialog because Gecko can not
|
||||
|
@ -73,12 +73,40 @@ interface nsIHelperAppLauncherDialog : nsISupports {
|
|||
* Set to true to force prompting the user for thet file
|
||||
* name/location, otherwise perferences may control if the user is
|
||||
* prompted.
|
||||
*
|
||||
* @throws NS_ERROR_NOT_AVAILABLE if the async version of this function
|
||||
* should be used.
|
||||
*/
|
||||
nsIFile promptForSaveToFile(in nsIHelperAppLauncher aLauncher,
|
||||
in nsISupports aWindowContext,
|
||||
in wstring aDefaultFileName,
|
||||
in wstring aSuggestedFileExtension,
|
||||
in boolean aForcePrompt);
|
||||
|
||||
/**
|
||||
* Async invoke a save-to-file dialog instead of the full fledged helper app
|
||||
* dialog. When the file is chosen (or the dialog is closed), the callback
|
||||
* in aLauncher (aLauncher.saveDestinationAvailable) is called with the
|
||||
* selected file.
|
||||
*
|
||||
* @param aLauncher
|
||||
* A nsIHelperAppLauncher to be invoked when a file is selected.
|
||||
* @param aWindowContext
|
||||
* Window associated with action.
|
||||
* @param aDefaultFileName
|
||||
* Default file name to provide (can be null)
|
||||
* @param aSuggestedFileExtension
|
||||
* Sugested file extension
|
||||
* @param aForcePrompt
|
||||
* Set to true to force prompting the user for thet file
|
||||
* name/location, otherwise perferences may control if the user is
|
||||
* prompted.
|
||||
*/
|
||||
void promptForSaveToFileAsync(in nsIHelperAppLauncher aLauncher,
|
||||
in nsISupports aWindowContext,
|
||||
in wstring aDefaultFileName,
|
||||
in wstring aSuggestedFileExtension,
|
||||
in boolean aForcePrompt);
|
||||
};
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче