Bug 1867080 - Implemented macOS functionality to find all other installed applications which support a protocol r=mhughes

Differential Revision: https://phabricator.services.mozilla.com/D195203
This commit is contained in:
Nipun Shukla 2023-12-04 21:54:20 +00:00
Родитель b4f96b0521
Коммит 41a15ef193
2 изменённых файлов: 82 добавлений и 0 удалений

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

@ -24,4 +24,19 @@ interface nsIMacShellService : nsIShellService
* * Privacy_Microphone
*/
void showSecurityPreferences(in ACString aPaneID);
/*
* Searches for any available handlers for the given protocol and returns them in an
* array in the form [[displayName1, handlerPath1], [displayName2, handlerPath2], etc.]
* Can return an empty array if no handlers are found.
*
* @param protocol The protocol to search for handlers for (e.g. "http", "mailto" etc.)
* @return The full list of handler paths and names.
*
* @throws NS_ERROR_ILLEGAL_VALUE if the protocol cannot be resolved as a string.
* @throws NS_ERROR_MALFORMED_URI if the protocol cannot be resolved to a URI.
* @throws NS_ERROR_NOT_AVAILABLE if a list of handlers fails to generate.
*/
Array<Array<AString> > getAvailableApplicationsForProtocol(in ACString protocol);
};

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

@ -277,3 +277,70 @@ nsMacShellService::ShowSecurityPreferences(const nsACString& aPaneID) {
}
return rv;
}
nsString ConvertCFStringToNSString(CFStringRef aSrc) {
nsString aDest;
auto len = ::CFStringGetLength(aSrc);
aDest.SetLength(len);
::CFStringGetCharacters(aSrc, ::CFRangeMake(0, len),
(UniChar*)aDest.BeginWriting());
return aDest;
}
NS_IMETHODIMP
nsMacShellService::GetAvailableApplicationsForProtocol(
const nsACString& protocol, nsTArray<nsTArray<nsString>>& aHandlerPaths) {
class CFTypeRefAutoDeleter {
public:
CFTypeRefAutoDeleter(CFTypeRef ref) : mRef(ref) {}
~CFTypeRefAutoDeleter() {
if (mRef != NULL) ::CFRelease(mRef);
}
private:
CFTypeRef mRef;
};
aHandlerPaths.Clear();
nsCString protocolSep = protocol + "://"_ns;
CFStringRef cfProtocol = ::CFStringCreateWithBytes(
kCFAllocatorDefault, (const UInt8*)protocolSep.BeginReading(),
protocolSep.Length(), kCFStringEncodingUTF8, false);
CFTypeRefAutoDeleter cfProtocolAuto(cfProtocol);
if (cfProtocol == NULL) {
return NS_ERROR_ILLEGAL_VALUE;
}
CFURLRef protocolURL =
::CFURLCreateWithString(kCFAllocatorDefault, cfProtocol, NULL);
CFTypeRefAutoDeleter cfProtocolURLAuto(protocolURL);
if (protocolURL == NULL) {
return NS_ERROR_MALFORMED_URI;
}
CFArrayRef appURLs = ::LSCopyApplicationURLsForURL(protocolURL, kLSRolesAll);
CFTypeRefAutoDeleter cfAppURLsAuto(appURLs);
if (appURLs == NULL) {
return NS_ERROR_NOT_AVAILABLE;
}
for (CFIndex i = 0; i < ::CFArrayGetCount(appURLs); i++) {
CFURLRef appURL = (CFURLRef)::CFArrayGetValueAtIndex(appURLs, i);
CFBundleRef appBundle = ::CFBundleCreate(kCFAllocatorDefault, appURL);
CFTypeRefAutoDeleter cfAppBundleAuto(appBundle);
if (appBundle == NULL) {
continue;
}
CFDictionaryRef appInfo = ::CFBundleGetInfoDictionary(appBundle);
if (appInfo == NULL) {
continue;
}
CFStringRef displayName =
(CFStringRef)::CFDictionaryGetValue(appInfo, kCFBundleNameKey);
if (displayName == NULL) {
continue;
}
CFStringRef appPath = ::CFURLGetString(appURL);
nsTArray<nsString> handlerPath = {ConvertCFStringToNSString(displayName),
ConvertCFStringToNSString(appPath)};
aHandlerPaths.AppendElement(handlerPath.Clone());
}
return NS_OK;
}