To complicate matter a bit more, there is a _new_ nsIProcess which allows more
control of running applications. Lets not add another
entrypoint on nsIFile|nsILocalFile. Can either Spawn or, better yet, nsIProcess be
modify for your application?
Also, I don't think that |reveal| belongs on nsILocalFile. This seams like a higher
level service, like a desktop or windowing interface.
I am going to cc the moz newsgroup.
Simon Fraser wrote:
> Scott MacGregor wrote:
> >
> > Here's the diff for implementing a reveal and a launch method off of
> > nsILocalFile for the mac. Launch is used to simulate double clicking the
> > file on the desktop so I'm just sending an open event.
> >
> > I have several questions as I post this code for review:
> > 1) Can I leverage LaunchAppWithDoc or LaunchDocWithApp for my open
> > event? i.e. can my launch method call one of these instead of the
> > implementation I wrote? Looking at the code I don't think so. They don't
> > appear to be posting a basic open event. But I thought I'd ask.
> > 2) All of the code in ::Lauch I got from Paul on an application he
> > worked on in the past. I don't understand what I'm doing with regards to
> > the code for creating a new FS spec for the directory containing the
> > file and then calling methods like newAlias and HLock/HUnlock.
> >
> > I guess I don't have any questions about the reveal method just the
> > above questions in launch.
>
> How does nsILocalFile.launch differ from nsIFile.spawn? They appear
> to have similar functionality, though spawn assumes that the nsIFile is
> pointing to an executable. It's odd, though, that spawn and launch
> have related functionality, yet are on different interfaces.
>
> Also, your implementation of Launch on the Mac overlaps with
> functionality provided by nsLocalFile::OpenDocWithApp(). It sends
> an AE to the Finder to launch the app. This will almost always
> have the same outcome as calling nsILocalFileMac::OpenDocWithApp()
> with a NULL aAppToOpenWith param, so it might just be easier
> (and certainly faster) to call that. Perhaps Conrad has input here.
>
> Simon
>
> >
> > ------------------------------------------------------------------------
> > ? 2.cpp
> > ? Bug63346ForMac.diff
> > ? Debug
> > ? doug.diff
> > ? mac.diff
> > ? nsLocalFileMac.diff
> > Index: nsILocalFile.idl
> > ===================================================================
> > RCS file: /cvsroot/mozilla/xpcom/io/nsILocalFile.idl,v
> > retrieving revision 1.12
> > diff -u -r1.12 nsILocalFile.idl
> > --- nsILocalFile.idl 2000/09/19 00:22:40 1.12
> > +++ nsILocalFile.idl 2001/01/29 20:00:20
> > @@ -101,6 +101,19 @@
> > */
> > attribute string persistentDescriptor;
> >
> > + /**
> > + * reveal --> Ask the operating system to open the folder which contains
> > + * this file or folder. This routine only works on platforms which
> > + * support the ability to open a folder...
> > + */
> > + void reveal();
> > +
> > + /**
> > + * launch --> Ask the operating system to attempt to open the file.
> > + * this really just simulates "double clicking" the file on your platform.
> > + * This routine only works on platforms which support this functionality.
> > + */
> > + void launch();
> > };
> >
> > %{C++
> > Index: nsLocalFileMac.cpp
> > ===================================================================
> > RCS file: /cvsroot/mozilla/xpcom/io/nsLocalFileMac.cpp,v
> > retrieving revision 1.50
> > diff -u -r1.50 nsLocalFileMac.cpp
> > --- nsLocalFileMac.cpp 2001/01/17 20:23:06 1.50
> > +++ nsLocalFileMac.cpp 2001/01/29 20:00:20
> > @@ -51,6 +51,7 @@
> >
> > #include <AppleEvents.h>
> > #include <AEDataModel.h>
> > +#include <AERegistry.h>
> >
> > #include <Math64.h>
> > #include <Aliases.h>
> > @@ -2375,6 +2376,116 @@
> > }
> >
> > return NS_OK;
> > +}
> > +
> > +#define aeSelectionKeyword 'fsel'
> > +#define kAEOpenSelection 'sope'
> > +#define kAERevealSelection 'srev'
> > +#define kFinderType 'FNDR'
> > +
> > +NS_IMETHODIMP nsLocalFile::Launch()
> > +{
> > + AppleEvent aeEvent = {0, nil};
> > + AppleEvent aeReply = {0, nil};
> > + StAEDesc aeDirDesc, listElem, myAddressDesc, fileList;
> > + FSSpec dirSpec, appSpec;
> > + AliasHandle DirAlias, FileAlias;
> > + OSErr errorResult = noErr;
> > + ProcessSerialNumber process;
> > +
> > + nsresult rv = FindRunningAppBySignature ('MACS', appSpec, process);
> > + if (NS_SUCCEEDED(rv))
> > + {
> > + errorResult = AECreateDesc(typeProcessSerialNumber, (Ptr)&process,
>sizeof(process), &myAddressDesc);
> > + if (errorResult == noErr)
> > + {
> > + /* Create the FinderEvent */
> > + errorResult = AECreateAppleEvent(kFinderType, kAEOpenSelection,
>&myAddressDesc, kAutoGenerateReturnID, kAnyTransactionID,
> > + &aeEvent);
> > + if (errorResult == noErr)
> > + {
> > + errorResult = FSMakeFSSpec(mResolvedSpec.vRefNum, mResolvedSpec.parID,
>nil, &dirSpec);
> > + NewAlias(nil, &dirSpec, &DirAlias);
> > + /* Create alias for file */
> > + NewAlias(nil, &mResolvedSpec, &FileAlias);
> > +
> > + /* Create the file list */
> > + errorResult = AECreateList(nil, 0, false, &fileList);
> > + /* create the folder descriptor */
> > + HLock((Handle)DirAlias);
> > + errorResult = AECreateDesc(typeAlias, (Ptr)*DirAlias,
>GetHandleSize((Handle)DirAlias), &aeDirDesc);
> > + HUnlock((Handle)DirAlias);
> > + if (errorResult == noErr)
> > + {
> > + errorResult = AEPutParamDesc(&aeEvent, keyDirectObject,
>&aeDirDesc);
> > + if ( errorResult == noErr)
> > + {
> > + /* create the file descriptor and add to aliasList */
> > + HLock((Handle)FileAlias);
> > + errorResult = AECreateDesc(typeAlias, (Ptr)*FileAlias,
>GetHandleSize((Handle)FileAlias), &listElem);
> > + HLock((Handle)FileAlias);
> > + if (errorResult == noErr)
> > + {
> > + errorResult = AEPutDesc(&fileList, 0, &listElem);
> > + if (errorResult == noErr)
> > + {
> > + /* Add the file alias list to the event */
> > + errorResult = AEPutParamDesc(&aeEvent,
>aeSelectionKeyword, &fileList);
> > + if (errorResult == noErr)
> > + AESend(&aeEvent, &aeReply, kAEWaitReply +
>kAENeverInteract
> > + + kAECanSwitchLayer,
>kAEHighPriority, kAEDefaultTimeout, nil, nil);
> > + }
> > + }
> > + }
> > + }
> > + }
> > + }
> > + }
> > +
> > + return NS_OK;
> > +}
> > +
> > +NS_IMETHODIMP nsLocalFile::Reveal()
> > +{
> > + AppleEvent aeEvent = {0, nil};
> > + AppleEvent aeReply = {0, nil};
> > + StAEDesc aeDirDesc, listElem, myAddressDesc, fileList;
> > + OSErr errorResult = noErr;
> > + ProcessSerialNumber process;
> > + FSSpec appSpec;
> > +
> > + nsresult rv = FindRunningAppBySignature ('MACS', appSpec, process);
> > + if (NS_SUCCEEDED(rv))
> > + {
> > + errorResult = AECreateDesc(typeProcessSerialNumber, (Ptr)&process,
>sizeof(process), &myAddressDesc);
> > + if (errorResult == noErr)
> > + {
> > + /* Create the FinderEvent */
> > + errorResult = AECreateAppleEvent(kFinderType, kAERevealSelection,
>&myAddressDesc, kAutoGenerateReturnID, kAnyTransactionID,
> > + &aeEvent);
> > + if (errorResult == noErr)
> > + {
> > + /* Create the file list */
> > + errorResult = AECreateList(nil, 0, false, &fileList);
> > + if (errorResult == noErr)
> > + {
> > + errorResult = AEPutPtr(&fileList, 0, typeFSS, &mResolvedSpec,
>sizeof(FSSpec));
> > + if (errorResult == noErr)
> > + {
> > + errorResult = AEPutParamDesc(&aeEvent,keySelection, &fileList);
> > + if (errorResult == noErr)
> > + {
> > + errorResult = AESend(&aeEvent, &aeReply, kAENoReply,
>kAENormalPriority, kAEDefaultTimeout, nil, nil);
> > + if (errorResult == noErr)
> > + SetFrontProcess(&process);
> > + }
> > + }
> > + }
> > + }
> > + }
> > + }
> > +
> > + return NS_OK;
> > }
> >
> > nsresult nsLocalFile::MyLaunchAppWithDoc(const FSSpec& appSpec, const FSSpec*
>aDocToLoad, PRBool aLaunchInBackground)
> > Index: nsLocalFileOS2.cpp
> > ===================================================================
> > RCS file: /cvsroot/mozilla/xpcom/io/nsLocalFileOS2.cpp,v
> > retrieving revision 1.22
> > diff -u -r1.22 nsLocalFileOS2.cpp
> > --- nsLocalFileOS2.cpp 2000/11/28 23:26:02 1.22
> > +++ nsLocalFileOS2.cpp 2001/01/29 20:00:21
> > @@ -2178,6 +2178,18 @@
> > return InitWithPath(aPersistentDescriptor);
> > }
> >
> > +NS_IMETHODIMP
> > +nsLocalFile::Reveal()
> > +{
> > + return NS_ERROR_FAILURE;
> > +}
> > +
> > +
> > +NS_IMETHODIMP
> > +nsLocalFile::Launch()
> > +{
> > + return NS_ERROR_FAILURE;
> > +}
> >
> > nsresult
> > NS_NewLocalFile(const char* path, PRBool followLinks, nsILocalFile* *result)
> > Index: nsLocalFileUnix.cpp
> > ===================================================================
> > RCS file: /cvsroot/mozilla/xpcom/io/nsLocalFileUnix.cpp,v
> > retrieving revision 1.41
> > diff -u -r1.41 nsLocalFileUnix.cpp
> > --- nsLocalFileUnix.cpp 2000/11/28 01:43:09 1.41
> > +++ nsLocalFileUnix.cpp 2001/01/29 20:00:21
> > @@ -1333,6 +1333,19 @@
> > return InitWithPath(aPersistentDescriptor);
> > }
> >
> > +NS_IMETHODIMP
> > +nsLocalFile::Reveal()
> > +{
> > + return NS_ERROR_FAILURE;
> > +}
> > +
> > +
> > +NS_IMETHODIMP
> > +nsLocalFile::Launch()
> > +{
> > + return NS_ERROR_FAILURE;
> > +}
> > +
> > nsresult
> > NS_NewLocalFile(const char *path, PRBool followSymlinks, nsILocalFile **result)
> > {
> > Index: nsLocalFileWin.cpp
> > ===================================================================
> > RCS file: /cvsroot/mozilla/xpcom/io/nsLocalFileWin.cpp,v
> > retrieving revision 1.49
> > diff -u -r1.49 nsLocalFileWin.cpp
> > --- nsLocalFileWin.cpp 2000/11/28 23:26:02 1.49
> > +++ nsLocalFileWin.cpp 2001/01/29 20:00:21
> > @@ -44,6 +44,7 @@
> > #include <stdlib.h>
> > #include <mbstring.h>
> >
> > +#include "nsXPIDLString.h"
> > #include "prproces.h"
> >
> > // certainly not all the error that can be
> > @@ -1911,6 +1912,53 @@
> > return InitWithPath(aPersistentDescriptor);
> > }
> >
> > +NS_IMETHODIMP
> > +nsLocalFile::Reveal()
> > +{
> > + nsresult rv = NS_OK;
> > + PRBool isDirectory = PR_FALSE;
> > + nsXPIDLCString path;
> > +
> > + IsDirectory(&isDirectory);
> > + if (isDirectory)
> > + {
> > + GetPath(getter_Copies(path));
> > + }
> > + else
> > + {
> > + nsCOMPtr<nsIFile> parent;
> > + GetParent(getter_AddRefs(parent));
> > + if (parent)
> > + parent->GetPath(getter_Copies(path));
> > + }
> > +
> > + // use the app registry name to launch a shell execute....
> > + LONG r = (LONG) ::ShellExecute( NULL, "explore", (const char *) path, NULL,
>NULL, SW_SHOWNORMAL);
> > + if (r < 32)
> > + rv = NS_ERROR_FAILURE;
> > + else
> > + rv = NS_OK;
> > +
> > + return rv;
> > +}
> > +
> > +
> > +NS_IMETHODIMP
> > +nsLocalFile::Launch()
> > +{
> > + nsresult rv = NS_OK;
> > + nsXPIDLCString path;
> > + GetPath(getter_Copies(path));
> > +
> > + // use the app registry name to launch a shell execute....
> > + LONG r = (LONG) ::ShellExecute( NULL, "open", (const char *) path, NULL, NULL,
>SW_SHOWNORMAL);
> > + if (r < 32)
> > + rv = NS_ERROR_FAILURE;
> > + else
> > + rv = NS_OK;
> > +
> > + return rv;
> > +}
> >
> > nsresult
> > NS_NewLocalFile(const char* path, PRBool followLinks, nsILocalFile* *result)