Skip to content

Commit 41a15ef

Browse files
committed
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
1 parent b4f96b0 commit 41a15ef

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

browser/components/shell/nsIMacShellService.idl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,19 @@ interface nsIMacShellService : nsIShellService
2424
* * Privacy_Microphone
2525
*/
2626
void showSecurityPreferences(in ACString aPaneID);
27+
28+
/*
29+
* Searches for any available handlers for the given protocol and returns them in an
30+
* array in the form [[displayName1, handlerPath1], [displayName2, handlerPath2], etc.]
31+
* Can return an empty array if no handlers are found.
32+
*
33+
* @param protocol The protocol to search for handlers for (e.g. "http", "mailto" etc.)
34+
* @return The full list of handler paths and names.
35+
*
36+
* @throws NS_ERROR_ILLEGAL_VALUE if the protocol cannot be resolved as a string.
37+
* @throws NS_ERROR_MALFORMED_URI if the protocol cannot be resolved to a URI.
38+
* @throws NS_ERROR_NOT_AVAILABLE if a list of handlers fails to generate.
39+
*/
40+
41+
Array<Array<AString> > getAvailableApplicationsForProtocol(in ACString protocol);
2742
};

browser/components/shell/nsMacShellService.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,3 +277,70 @@ nsMacShellService::ShowSecurityPreferences(const nsACString& aPaneID) {
277277
}
278278
return rv;
279279
}
280+
281+
nsString ConvertCFStringToNSString(CFStringRef aSrc) {
282+
nsString aDest;
283+
auto len = ::CFStringGetLength(aSrc);
284+
aDest.SetLength(len);
285+
::CFStringGetCharacters(aSrc, ::CFRangeMake(0, len),
286+
(UniChar*)aDest.BeginWriting());
287+
return aDest;
288+
}
289+
290+
NS_IMETHODIMP
291+
nsMacShellService::GetAvailableApplicationsForProtocol(
292+
const nsACString& protocol, nsTArray<nsTArray<nsString>>& aHandlerPaths) {
293+
class CFTypeRefAutoDeleter {
294+
public:
295+
CFTypeRefAutoDeleter(CFTypeRef ref) : mRef(ref) {}
296+
~CFTypeRefAutoDeleter() {
297+
if (mRef != NULL) ::CFRelease(mRef);
298+
}
299+
300+
private:
301+
CFTypeRef mRef;
302+
};
303+
304+
aHandlerPaths.Clear();
305+
nsCString protocolSep = protocol + "://"_ns;
306+
CFStringRef cfProtocol = ::CFStringCreateWithBytes(
307+
kCFAllocatorDefault, (const UInt8*)protocolSep.BeginReading(),
308+
protocolSep.Length(), kCFStringEncodingUTF8, false);
309+
CFTypeRefAutoDeleter cfProtocolAuto(cfProtocol);
310+
if (cfProtocol == NULL) {
311+
return NS_ERROR_ILLEGAL_VALUE;
312+
}
313+
CFURLRef protocolURL =
314+
::CFURLCreateWithString(kCFAllocatorDefault, cfProtocol, NULL);
315+
CFTypeRefAutoDeleter cfProtocolURLAuto(protocolURL);
316+
if (protocolURL == NULL) {
317+
return NS_ERROR_MALFORMED_URI;
318+
}
319+
CFArrayRef appURLs = ::LSCopyApplicationURLsForURL(protocolURL, kLSRolesAll);
320+
CFTypeRefAutoDeleter cfAppURLsAuto(appURLs);
321+
if (appURLs == NULL) {
322+
return NS_ERROR_NOT_AVAILABLE;
323+
}
324+
for (CFIndex i = 0; i < ::CFArrayGetCount(appURLs); i++) {
325+
CFURLRef appURL = (CFURLRef)::CFArrayGetValueAtIndex(appURLs, i);
326+
CFBundleRef appBundle = ::CFBundleCreate(kCFAllocatorDefault, appURL);
327+
CFTypeRefAutoDeleter cfAppBundleAuto(appBundle);
328+
if (appBundle == NULL) {
329+
continue;
330+
}
331+
CFDictionaryRef appInfo = ::CFBundleGetInfoDictionary(appBundle);
332+
if (appInfo == NULL) {
333+
continue;
334+
}
335+
CFStringRef displayName =
336+
(CFStringRef)::CFDictionaryGetValue(appInfo, kCFBundleNameKey);
337+
if (displayName == NULL) {
338+
continue;
339+
}
340+
CFStringRef appPath = ::CFURLGetString(appURL);
341+
nsTArray<nsString> handlerPath = {ConvertCFStringToNSString(displayName),
342+
ConvertCFStringToNSString(appPath)};
343+
aHandlerPaths.AppendElement(handlerPath.Clone());
344+
}
345+
return NS_OK;
346+
}

0 commit comments

Comments
 (0)