local protocol handling apps can be chosen but don't work (bug 389758); patch by dolske and me, r=biesi, sr=bz, a=mconnor

This commit is contained in:
dmose@mozilla.org 2007-07-28 20:38:52 -07:00
parent 0eb5fca39a
commit 37bc219194
4 changed files with 109 additions and 21 deletions

View File

@ -69,19 +69,40 @@ nsMIMEInfoMac::LaunchWithURI(nsIURI* aURI)
rv = localHandlerApp->GetExecutable(getter_AddRefs(application));
NS_ENSURE_SUCCESS(rv, rv);
} else if (mPreferredAction == useSystemDefault)
} else if (mPreferredAction == useSystemDefault) {
// because nsMIMEInfoMac isn't yet set up with mDefaultApplication
// in the protocol handler case, we need to do it another way for now
// (which is fine, but this code would be a little more readable if we
// could fall through this case).
if (mClass == eProtocolInfo) {
return LoadUriInternal(aURI);
}
application = mDefaultApplication;
}
else
return NS_ERROR_INVALID_ARG;
if (mClass == eProtocolInfo)
return LoadUriInternal(aURI);
// get the nsILocalFile version of the doc to launch with
nsCOMPtr<nsILocalFile> docToLoad;
rv = GetLocalFileFromURI(aURI, getter_AddRefs(docToLoad));
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(rv)) {
// If we don't have a file, we must be a protocol handler
NS_ASSERTION(mClass == eProtocolInfo,
"nsMIMEInfoMac should be a protocol handler");
// so pass the entire URI to the handler.
nsCAutoString spec;
aURI->GetSpec(spec);
return OpenApplicationWithURI(application, spec);
}
// note that the file pointed to by docToLoad could possibly have originated
// as a file: URI if we're in some non-browser application.
// if we've already got an app, just QI so we have the launchWithDoc method
nsCOMPtr<nsILocalFileMac> app;
if (application) {
@ -134,3 +155,51 @@ nsMIMEInfoMac::GetHasDefaultHandler(PRBool *_retval)
return NS_OK;
}
/**
* static; mostly copy/pasted from nsMacShellService.cpp (which is in browser/,
* so we can't depend on it here). This code probably really wants to live
* somewhere more central; see bug 389922.
*/
nsresult
nsMIMEInfoMac::OpenApplicationWithURI(nsIFile* aApplication,
const nsCString& aURI)
{
nsresult rv;
nsCOMPtr<nsILocalFileMac> lfm(do_QueryInterface(aApplication, &rv));
NS_ENSURE_SUCCESS(rv, rv);
CFURLRef appURL;
rv = lfm->GetCFURL(&appURL);
if (NS_FAILED(rv))
return rv;
const UInt8* uriString = (const UInt8*)aURI.get();
CFURLRef uri = ::CFURLCreateWithBytes(NULL, uriString, aURI.Length(),
kCFStringEncodingUTF8, NULL);
if (!uri) {
::CFRelease(appURL);
return NS_ERROR_OUT_OF_MEMORY;
}
CFArrayRef uris = ::CFArrayCreate(NULL, (const void**)&uri, 1, NULL);
if (!uris) {
::CFRelease(uri);
::CFRelease(appURL);
return NS_ERROR_OUT_OF_MEMORY;
}
LSLaunchURLSpec launchSpec;
launchSpec.appURL = appURL;
launchSpec.itemURLs = uris;
launchSpec.passThruParams = NULL;
launchSpec.launchFlags = kLSLaunchDefaults;
launchSpec.asyncRefCon = NULL;
OSErr err = ::LSOpenFromURLSpec(&launchSpec, NULL);
::CFRelease(uris);
::CFRelease(uri);
::CFRelease(appURL);
return err != noErr ? NS_ERROR_FAILURE : NS_OK;
}

View File

@ -56,6 +56,9 @@ class nsMIMEInfoMac : public nsMIMEInfoImpl {
return NS_ERROR_UNEXPECTED;
}
#endif
static NS_HIDDEN_(nsresult) OpenApplicationWithURI(nsIFile *aApplication,
const nsCString& aURI);
};

View File

@ -358,10 +358,26 @@ nsMIMEInfoBase::LaunchWithURI(nsIURI* aURI)
rv = localHandler->GetExecutable(getter_AddRefs(executable));
NS_ENSURE_SUCCESS(rv, rv);
// get the nsILocalFile version of the doc to launch with
rv = GetLocalFileFromURI(aURI, getter_AddRefs(docToLoad));
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(rv)) {
return LaunchWithIProcess(executable, docToLoad);
// If we don't have a file, we must be a protocol handler
NS_ASSERTION(mClass == eProtocolInfo,
"nsMIMEInfoBase should be a protocol handler");
// so pass the entire URI to the handler.
nsCAutoString spec;
aURI->GetSpec(spec);
return LaunchWithIProcess(executable, spec);
}
// note that the file pointed to by docToLoad could possibly have
// originated as a file: URI if we're in some non-browser application.
nsCAutoString path;
docToLoad->GetNativePath(path);
return LaunchWithIProcess(executable, path);
}
else if (mPreferredAction == useSystemDefault) {
if (mClass == eProtocolInfo)
@ -389,9 +405,9 @@ nsMIMEInfoBase::CopyBasicDataTo(nsMIMEInfoBase* aOther)
/* static */
nsresult
nsMIMEInfoBase::LaunchWithIProcess(nsIFile* aApp, nsIFile* aFile)
nsMIMEInfoBase::LaunchWithIProcess(nsIFile* aApp, const nsCString& aArg)
{
NS_ASSERTION(aApp && aFile, "Unexpected null pointer, fix caller");
NS_ASSERTION(aApp, "Unexpected null pointer, fix caller");
nsresult rv;
nsCOMPtr<nsIProcess> process = do_CreateInstance(NS_PROCESS_CONTRACTID, &rv);
@ -401,13 +417,10 @@ nsMIMEInfoBase::LaunchWithIProcess(nsIFile* aApp, nsIFile* aFile)
if (NS_FAILED(rv = process->Init(aApp)))
return rv;
nsCAutoString path;
aFile->GetNativePath(path);
const char * strPath = path.get();
const char *string = aArg.get();
PRUint32 pid;
return process->Run(PR_FALSE, &strPath, 1, &pid);
return process->Run(PR_FALSE, &string, 1, &pid);
}
/* static */
@ -450,6 +463,9 @@ nsMIMEInfoImpl::LaunchDefaultWithFile(nsIFile* aFile)
if (!mDefaultApplication)
return NS_ERROR_FILE_NOT_FOUND;
return LaunchWithIProcess(mDefaultApplication, aFile);
nsCAutoString nativePath;
aFile->GetNativePath(nativePath);
return LaunchWithIProcess(mDefaultApplication, nativePath);
}

View File

@ -140,16 +140,16 @@ class nsMIMEInfoBase : public nsIMIMEInfo {
virtual NS_HIDDEN_(nsresult) LoadUriInternal(nsIURI *aURI) = 0;
/**
* This method can be used to launch the file using nsIProcess, with the
* path of the file being the first parameter to the executable. This is
* This method can be used to launch the file or URI with a single
* argument (typically either a file path or a URI spec). This is
* meant as a helper method for implementations of
* LaunchWithFile/LaunchDefaultWithFile.
* Neither aApp nor aFile may be null.
* LaunchWithURI/LaunchDefaultWithFile.
*
* @param aApp The application to launch
* @param aFile The file to open in the application
* @param aApp The application to launch (may not be null)
* @param aArg The argument to pass on the command line
*/
static NS_HIDDEN_(nsresult) LaunchWithIProcess(nsIFile* aApp, nsIFile* aFile);
static NS_HIDDEN_(nsresult) LaunchWithIProcess(nsIFile* aApp,
const nsCString &aArg);
/**
* Used to launch a web-based handler with this URI.