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:
mscott%netscape.com 2000-07-07 01:48:05 +00:00
Родитель 021eb5de93
Коммит d4124c9ef0
3 изменённых файлов: 178 добавлений и 63 удалений

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

@ -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();
};