зеркало из https://github.com/mozilla/pjs.git
Bug #43583 --> re-organizing how we launch helper apps to work with the helper app dialog.
Add nsIExternalAppLauncher interface which is used by the helper app dialog. r=alecf
This commit is contained in:
Родитель
021eb5de93
Коммит
d4124c9ef0
|
@ -112,11 +112,7 @@ nsresult nsExternalHelperAppService::Init()
|
|||
rdf->GetResource(NC_RDF_PRETTYNAME, getter_AddRefs(kNC_PrettyName));
|
||||
}
|
||||
|
||||
#ifdef DEBUG_mscott
|
||||
nsCOMPtr<nsIMIMEInfo> mimeInfo;
|
||||
GetMIMEInfoForMimeType("application/pdf", getter_AddRefs(mimeInfo));
|
||||
#endif
|
||||
return rv;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* boolean canHandleContent (in string aMimeContentType); */
|
||||
|
@ -140,31 +136,14 @@ NS_IMETHODIMP nsExternalHelperAppService::DoContent(const char *aMimeContentType
|
|||
|
||||
if (NS_SUCCEEDED(rv) && mimeInfo)
|
||||
{
|
||||
// test to see if we should save to disk or use a helper application.
|
||||
// eventually we'll add code to handle the ask me case...
|
||||
nsMIMEInfoHandleAction action = nsIMIMEInfo::useHelperApp;
|
||||
mimeInfo->GetPreferredAction(&action);
|
||||
if (action == nsIMIMEInfo::saveToDisk)
|
||||
{
|
||||
// for the save to disk case, just pretened we don't want to handle it and the uri loader will eventually
|
||||
// bring up the save to disk dialog for us!!
|
||||
return NS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
// try to see if we have a user specified application to launch with this content type.
|
||||
nsCOMPtr<nsIFile> application;
|
||||
mimeInfo->GetPreferredApplicationHandler(getter_AddRefs(application));
|
||||
if (application)
|
||||
{
|
||||
// ask the OS specific subclass to create a stream listener for us that binds this suggested application
|
||||
// even if this fails, return NS_OK...
|
||||
nsXPIDLCString fileExtension;
|
||||
mimeInfo->FirstExtension(getter_Copies(fileExtension));
|
||||
CreateStreamListenerWithApp(application, fileExtension, aStreamListener);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
// ask the OS specific subclass to create a stream listener for us that binds this suggested application
|
||||
// even if this fails, return NS_OK...
|
||||
nsXPIDLCString fileExtension;
|
||||
mimeInfo->FirstExtension(getter_Copies(fileExtension));
|
||||
nsExternalAppHandler * app = CreateNewExternalHandler(mimeInfo, fileExtension);
|
||||
if (app)
|
||||
app->QueryInterface(NS_GET_IID(nsIStreamListener), (void **) aStreamListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// if we made it here, then we were unable to handle this ourselves..return an error so the
|
||||
|
@ -172,13 +151,13 @@ NS_IMETHODIMP nsExternalHelperAppService::DoContent(const char *aMimeContentType
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsExternalHelperAppService::LaunchAppWithTempFile(nsIFile * aTempFile, nsISupports * aAppCookie)
|
||||
NS_IMETHODIMP nsExternalHelperAppService::LaunchAppWithTempFile(nsIMIMEInfo * aMimeInfo, nsIFile * aTempFile)
|
||||
{
|
||||
// this method should only be implemented by each OS specific implementation of this service.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsExternalAppHandler * nsExternalHelperAppService::CreateNewExternalHandler(nsISupports * aAppCookie,
|
||||
nsExternalAppHandler * nsExternalHelperAppService::CreateNewExternalHandler(nsIMIMEInfo * aMIMEInfo,
|
||||
const char * aTempFileExtension)
|
||||
{
|
||||
nsExternalAppHandler* handler = nsnull;
|
||||
|
@ -186,7 +165,7 @@ nsExternalAppHandler * nsExternalHelperAppService::CreateNewExternalHandler(nsIS
|
|||
// add any XP intialization code for an external handler that we may need here...
|
||||
// right now we don't have any but i bet we will before we are done.
|
||||
|
||||
handler->Init(aAppCookie, aTempFileExtension);
|
||||
handler->Init(aMIMEInfo, aTempFileExtension);
|
||||
return handler;
|
||||
}
|
||||
|
||||
|
@ -398,12 +377,15 @@ NS_INTERFACE_MAP_BEGIN(nsExternalAppHandler)
|
|||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIStreamObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIHelperAppLauncher)
|
||||
NS_INTERFACE_MAP_END_THREADSAFE
|
||||
|
||||
nsExternalAppHandler::nsExternalAppHandler()
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
|
||||
mCanceled = PR_FALSE;
|
||||
mReceivedDispostionInfo = PR_FALSE;
|
||||
mStopRequestIssued = PR_FALSE;
|
||||
mDataBuffer = (char *) nsMemory::Alloc((sizeof(char) * DATA_BUFFER_SIZE));
|
||||
}
|
||||
|
||||
|
@ -413,9 +395,9 @@ nsExternalAppHandler::~nsExternalAppHandler()
|
|||
nsMemory::Free(mDataBuffer);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIChannel * aChannel, nsISupports * aCtxt)
|
||||
nsresult nsExternalAppHandler::SetUpTempFile(nsIChannel * aChannel)
|
||||
{
|
||||
NS_ENSURE_ARG(aChannel);
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
#ifdef XP_MAC
|
||||
// create a temp file for the data...and open it for writing.
|
||||
|
@ -457,10 +439,37 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIChannel * aChannel, nsISup
|
|||
nsCOMPtr<nsIFileChannel> mFileChannel = do_CreateInstance(NS_LOCALFILECHANNEL_PROGID);
|
||||
if (mFileChannel)
|
||||
{
|
||||
mFileChannel->Init(mTempFile, -1, 0);
|
||||
mFileChannel->OpenOutputStream(getter_AddRefs(mOutStream));
|
||||
rv = mFileChannel->Init(mTempFile, -1, 0);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = mFileChannel->OpenOutputStream(getter_AddRefs(mOutStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIChannel * aChannel, nsISupports * aCtxt)
|
||||
{
|
||||
NS_ENSURE_ARG(aChannel);
|
||||
|
||||
nsresult rv = SetUpTempFile(aChannel);
|
||||
|
||||
// now that the temp file is set up, find out if we need to invoke a dialog asking the user what
|
||||
// they want us to do with this content...
|
||||
|
||||
nsMIMEInfoHandleAction action = nsIMIMEInfo::alwaysAsk;
|
||||
mMimeInfo->GetPreferredAction(&action);
|
||||
if (action == nsIMIMEInfo::alwaysAsk)
|
||||
{
|
||||
// do this first! make sure we don't try to take an action until the user tells us what they want to do
|
||||
// with it...
|
||||
mReceivedDispostionInfo = PR_FALSE;
|
||||
|
||||
// invoke the dialog!!!!!
|
||||
}
|
||||
else
|
||||
mReceivedDispostionInfo = PR_TRUE; // no need to wait for a response from the user
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -491,6 +500,8 @@ NS_IMETHODIMP nsExternalAppHandler::OnStopRequest(nsIChannel * aChannel, nsISupp
|
|||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
mStopRequestIssued = PR_TRUE;
|
||||
|
||||
// go ahead and execute the application passing in our temp file as an argument
|
||||
// this may involve us calling back into the OS external app service to make the call
|
||||
// for actually launching the helper app. It'd be great if nsIFile::spawn could be made to work
|
||||
|
@ -500,18 +511,31 @@ NS_IMETHODIMP nsExternalAppHandler::OnStopRequest(nsIChannel * aChannel, nsISupp
|
|||
if (mOutStream)
|
||||
mOutStream->Close();
|
||||
|
||||
nsCOMPtr<nsPIExternalAppLauncher> helperAppService (do_GetService(NS_EXTERNALHELPERAPPSERVICE_PROGID));
|
||||
if (helperAppService)
|
||||
if (mReceivedDispostionInfo && !mCanceled)
|
||||
{
|
||||
rv = helperAppService->LaunchAppWithTempFile(mTempFile, mExternalApplication);
|
||||
nsMIMEInfoHandleAction action = nsIMIMEInfo::alwaysAsk;
|
||||
mMimeInfo->GetPreferredAction(&action);
|
||||
if (action == nsIMIMEInfo::saveToDisk)
|
||||
{
|
||||
#ifdef DEBUG_mscott
|
||||
// create a temp file for the data...and open it for writing.
|
||||
NS_GetSpecialDirectory("system.OS_TemporaryDirectory", getter_AddRefs(mFinalFileDestination));
|
||||
mFinalFileDestination->Append("foo.txt");
|
||||
#endif
|
||||
rv = SaveToDisk(mFinalFileDestination, PR_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = LaunchWithApplication(nsnull, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsExternalAppHandler::Init(nsISupports * aAppCookie, const char * aTempFileExtension)
|
||||
nsresult nsExternalAppHandler::Init(nsIMIMEInfo * aMIMEInfo, const char * aTempFileExtension)
|
||||
{
|
||||
mExternalApplication = aAppCookie;
|
||||
mMimeInfo = aMIMEInfo;
|
||||
|
||||
// make sure the extention includes the '.'
|
||||
if (aTempFileExtension && *aTempFileExtension != '.')
|
||||
|
@ -519,3 +543,67 @@ nsresult nsExternalAppHandler::Init(nsISupports * aAppCookie, const char * aTemp
|
|||
mTempFileExtension.Append(aTempFileExtension);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsExternalAppHandler::GetMIMEInfo(nsIMIMEInfo ** aMIMEInfo)
|
||||
{
|
||||
*aMIMEInfo = mMimeInfo;
|
||||
NS_IF_ADDREF(*aMIMEInfo);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsExternalAppHandler::SaveToDisk(nsIFile * aNewFileLocation, PRBool aRememberThisPreference)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
mReceivedDispostionInfo = PR_TRUE;
|
||||
if (mStopRequestIssued)
|
||||
{
|
||||
if (aNewFileLocation)
|
||||
{
|
||||
// extract the new leaf name from the file location
|
||||
nsXPIDLCString fileName;
|
||||
aNewFileLocation->GetLeafName(getter_Copies(fileName));
|
||||
nsCOMPtr<nsIFile> directoryLocation;
|
||||
aNewFileLocation->GetParent(getter_AddRefs(directoryLocation));
|
||||
if (directoryLocation)
|
||||
{
|
||||
rv = mTempFile->MoveTo(directoryLocation, fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
// o.t. remember the new file location to save to.
|
||||
else
|
||||
{
|
||||
mFinalFileDestination = aNewFileLocation;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsExternalAppHandler::LaunchWithApplication(nsIFile * aApplication, PRBool aRememberThisPreference)
|
||||
{
|
||||
mReceivedDispostionInfo = PR_TRUE;
|
||||
|
||||
// if a stop request was already issued then proceed with launching the application.
|
||||
nsresult rv = NS_OK;
|
||||
if (mStopRequestIssued)
|
||||
{
|
||||
nsCOMPtr<nsPIExternalAppLauncher> helperAppService (do_GetService(NS_EXTERNALHELPERAPPSERVICE_PROGID));
|
||||
if (helperAppService)
|
||||
{
|
||||
rv = helperAppService->LaunchAppWithTempFile(mMimeInfo, mTempFile);
|
||||
}
|
||||
}
|
||||
// o.t. remember the application we should use to launch the app and when the on stop request is issued, launch it.
|
||||
else
|
||||
{
|
||||
if (mMimeInfo)
|
||||
mMimeInfo->SetPreferredApplicationHandler(aApplication);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsExternalAppHandler::Cancel()
|
||||
{
|
||||
mCanceled = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "nsIExternalHelperAppService.h"
|
||||
#include "nsIExternalProtocolService.h"
|
||||
|
||||
#include "nsIMIMEInfo.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIFileStreams.h"
|
||||
|
@ -39,7 +40,6 @@
|
|||
class nsExternalAppHandler;
|
||||
class nsIMIMEInfo;
|
||||
class nsIRDFService;
|
||||
class nsIMIMEInfo;
|
||||
|
||||
class nsExternalHelperAppService : public nsIExternalHelperAppService, public nsPIExternalAppLauncher, public nsIExternalProtocolService
|
||||
{
|
||||
|
@ -54,10 +54,10 @@ public:
|
|||
nsresult Init();
|
||||
|
||||
// CreateNewExternalHandler is implemented only by the base class...
|
||||
// create an external app handler and bind it with a cookie that came from the OS specific
|
||||
// helper app service subclass.
|
||||
// create an external app handler and binds it with a mime info object which represents
|
||||
// how we want to dispose of this content
|
||||
// aFileExtension --> the extension we need to append to our temp file INCLUDING the ".". i.e. .mp3
|
||||
nsExternalAppHandler * CreateNewExternalHandler(nsISupports * aAppCookie, const char * aFileExtension);
|
||||
nsExternalAppHandler * CreateNewExternalHandler(nsIMIMEInfo * aMIMEInfo, const char * aFileExtension);
|
||||
|
||||
// GetMIMEInfoForMimeType --> this will eventually be part of an interface but for now
|
||||
// it's only used internally. Given a content type, look up the user override information to
|
||||
|
@ -70,12 +70,6 @@ public:
|
|||
// aFile --> an nsIFile representation of that platform application path.
|
||||
virtual nsresult GetFileTokenForPath(const PRUnichar * platformAppPath, nsIFile ** aFile) = 0;
|
||||
|
||||
// CreateStreamListenerWithApp --> must be implemented by each platform.
|
||||
// aApplicationToUse --> the application the user wishes to launch with the incoming data
|
||||
// aFileExtensionForData --> the extension we are going to use for the temp file in the external app handler
|
||||
// aStreamListener --> the stream listener (really a external app handler) we're going to use for retrieving the data
|
||||
virtual nsresult CreateStreamListenerWithApp(nsIFile * aApplicationToUse, const char * aFileExtensionForData, nsIStreamListener ** aStreamListener) = 0;
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIRDFDataSource> mOverRideDataSource;
|
||||
|
||||
|
@ -111,27 +105,41 @@ protected:
|
|||
// to write the data into the output stream representing the temp file...
|
||||
#define DATA_BUFFER_SIZE (4096*2)
|
||||
|
||||
class nsExternalAppHandler : public nsIStreamListener
|
||||
class nsExternalAppHandler : public nsIStreamListener, public nsIHelperAppLauncher
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSISTREAMOBSERVER
|
||||
NS_DECL_NSIHELPERAPPLAUNCHER
|
||||
|
||||
nsExternalAppHandler();
|
||||
virtual ~nsExternalAppHandler();
|
||||
|
||||
// initialize the handler with a cookie that represents the external
|
||||
// application associated with this handler.
|
||||
virtual nsresult Init(nsISupports * aExternalApplicationCookie, const char * aFileExtension);
|
||||
virtual nsresult Init(nsIMIMEInfo * aMIMEInfo, const char * aFileExtension);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIFile> mTempFile;
|
||||
nsCString mTempFileExtension;
|
||||
nsCOMPtr<nsISupports> mExternalApplication;
|
||||
nsCOMPtr<nsIMIMEInfo> mMimeInfo;
|
||||
nsCOMPtr<nsIOutputStream> mOutStream; // output stream to the temp file...
|
||||
|
||||
// the canceled flag is set if the user canceled the launching of this application before we finished
|
||||
// saving the data to a temp file...
|
||||
PRBool mCanceled;
|
||||
|
||||
// have we received information from the user about how they want to dispose of this content...
|
||||
PRBool mReceivedDispostionInfo;
|
||||
PRBool mStopRequestIssued;
|
||||
|
||||
// when we are told to save the temp file to disk (in a more permament location) before we are done
|
||||
// writing the content to a temp file, then we need to remember the final destination until we are ready to
|
||||
// use it.
|
||||
nsCOMPtr<nsIFile> mFinalFileDestination;
|
||||
|
||||
char * mDataBuffer;
|
||||
|
||||
nsresult SetUpTempFile(nsIChannel * aChannel);
|
||||
};
|
||||
|
||||
#endif // nsExternalHelperAppService_h__
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
interface nsIURI;
|
||||
interface nsIStreamListener;
|
||||
interface nsIFile;
|
||||
interface nsIMIMEInfo;
|
||||
|
||||
|
||||
[scriptable, uuid(663CC0AA-42EA-11d4-98D0-001083010E9B)]
|
||||
|
@ -62,9 +63,27 @@ interface nsPIExternalAppLauncher : nsISupports
|
|||
{
|
||||
// launchAppWithTempFile --> used by the handler to actually launch the helper application
|
||||
// aTempFile --> the file which contains the data we want the helper app to use when it is launched
|
||||
// aAppCookie --> a cookie that was given to the app handler when it was created by the OS specific
|
||||
// external helper app service. This cookie contains all the information the service
|
||||
// needs to know about the application in order to launch it. It's content differs by
|
||||
// platform.
|
||||
void launchAppWithTempFile(in nsIFile aTempFile, in nsISupports aAppCookie);
|
||||
void launchAppWithTempFile(in nsIMIMEInfo aMIMEInfo, in nsIFile aTempFile);
|
||||
};
|
||||
|
||||
// a helper app launcher is a small object created to handle the launching of an external application.
|
||||
|
||||
[scriptable, uuid(9503D0FE-4C9D-11d4-98D0-001083010E9B)]
|
||||
interface nsIHelperAppLauncher : nsISupports
|
||||
{
|
||||
// the mime info object associated with the content type this helper app launcher is currently
|
||||
// attempting to load
|
||||
readonly attribute nsIMIMEInfo MIMEInfo;
|
||||
|
||||
// saveToDisk: called when we want to just save the content to a particular file
|
||||
// aNewFileLocation --> location where the content should be saved
|
||||
void saveToDisk(in nsIFile aNewFileLocation, in boolean aRememberThisPreference);
|
||||
|
||||
// launchWithApplication: use aApplication to launch with this content
|
||||
// aApplication --> nsIFile corresponding to the location of the application to use
|
||||
// aRememberThisPreference --> TRUE if we should remember this choice.
|
||||
void launchWithApplication(in nsIFile aApplication, in boolean aRememberThisPreference);
|
||||
|
||||
// called if the user decides to cancel the handling of this content type
|
||||
void Cancel();
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче