local protocol handling apps can be chosen but don't work (
bug 389758); patch by dolske and me, r=biesi, sr=bz, a=mconnor
--- a/uriloader/exthandler/mac/nsMIMEInfoMac.cpp
+++ b/uriloader/exthandler/mac/nsMIMEInfoMac.cpp
@@ -64,29 +64,50 @@ nsMIMEInfoMac::LaunchWithURI(nsIURI* aUR
// otherwise, get the application executable from the handler
nsCOMPtr<nsILocalHandlerApp> localHandlerApp =
do_QueryInterface(mPreferredApplication, &rv);
NS_ENSURE_SUCCESS(rv, rv);
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) {
app = do_QueryInterface(application, &rv);
if (NS_FAILED(rv)) return rv;
} else {
// otherwise ask LaunchServices for an app directly
nsCOMPtr<nsILocalFileMac> tempFile = do_QueryInterface(docToLoad, &rv);
@@ -129,8 +150,56 @@ nsMIMEInfoMac::LoadUriInternal(nsIURI *a
NS_IMETHODIMP
nsMIMEInfoMac::GetHasDefaultHandler(PRBool *_retval)
{
// We have a default application if we have a description
*_retval = !mDefaultAppDescription.IsEmpty();
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;
+}
--- a/uriloader/exthandler/mac/nsMIMEInfoMac.h
+++ b/uriloader/exthandler/mac/nsMIMEInfoMac.h
@@ -51,12 +51,15 @@ class nsMIMEInfoMac : public nsMIMEInfoI
protected:
virtual NS_HIDDEN_(nsresult) LoadUriInternal(nsIURI *aURI);
#ifdef DEBUG
virtual NS_HIDDEN_(nsresult) LaunchDefaultWithFile(nsIFile* aFile) {
NS_NOTREACHED("do not call this method, use LaunchWithFile");
return NS_ERROR_UNEXPECTED;
}
#endif
+ static NS_HIDDEN_(nsresult) OpenApplicationWithURI(nsIFile *aApplication,
+ const nsCString& aURI);
+
};
#endif
--- a/uriloader/exthandler/nsMIMEInfoImpl.cpp
+++ b/uriloader/exthandler/nsMIMEInfoImpl.cpp
@@ -353,20 +353,36 @@ nsMIMEInfoBase::LaunchWithURI(nsIURI* aU
nsCOMPtr<nsILocalHandlerApp> localHandler =
do_QueryInterface(mPreferredApplication, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> executable;
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)) {
+
+ // If we don't have a file, we must be a protocol handler
+ NS_ASSERTION(mClass == eProtocolInfo,
+ "nsMIMEInfoBase should be a protocol handler");
- return LaunchWithIProcess(executable, docToLoad);
+ // 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)
return LoadUriInternal(aURI);
rv = GetLocalFileFromURI(aURI, getter_AddRefs(docToLoad));
NS_ENSURE_SUCCESS(rv, rv);
@@ -384,35 +400,32 @@ nsMIMEInfoBase::CopyBasicDataTo(nsMIMEIn
aOther->mExtensions = mExtensions;
aOther->mMacType = mMacType;
aOther->mMacCreator = mMacCreator;
}
/* 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);
if (NS_FAILED(rv))
return rv;
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 */
nsresult
nsMIMEInfoBase::LaunchWithWebHandler(nsIWebHandlerApp *aApp, nsIURI *aURI)
{
// we'll be implementing this Real Soon Now!
return NS_ERROR_NOT_IMPLEMENTED;
@@ -445,11 +458,14 @@ nsMIMEInfoImpl::GetHasDefaultHandler(PRB
}
nsresult
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);
}
--- a/uriloader/exthandler/nsMIMEInfoImpl.h
+++ b/uriloader/exthandler/nsMIMEInfoImpl.h
@@ -135,26 +135,26 @@ class nsMIMEInfoBase : public nsIMIMEInf
/**
* Loads the URI with the OS default app.
*
* @param aURI The URI to pass off to the OS.
*/
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.
*
* @param aURI The URI to launch with.
*/
static NS_HIDDEN_(nsresult) LaunchWithWebHandler(nsIWebHandlerApp *aApp,
nsIURI *aURI);