RNBServices.cpp revision 56b9f80df238c8be09d2b7441e9e71f7828bbd3a
1//===-- RNBServices.cpp -----------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  Created by Christopher Friesen on 3/21/08.
11//
12//===----------------------------------------------------------------------===//
13
14#import "RNBServices.h"
15
16#import <CoreFoundation/CoreFoundation.h>
17#import <unistd.h>
18#import "DNBLog.h"
19#include "MacOSX/CFUtils.h"
20
21#ifdef WITH_SPRINGBOARD
22#import <SpringBoardServices/SpringBoardServices.h>
23#endif
24
25int
26ListApplications(std::string& plist, bool opt_runningApps, bool opt_debuggable)
27{
28#ifdef WITH_SPRINGBOARD
29    int result = -1;
30
31    CFAllocatorRef alloc = kCFAllocatorDefault;
32
33    // Create a mutable array that we can populate. Specify zero so it can be of any size.
34    CFReleaser<CFMutableArrayRef> plistMutableArray (::CFArrayCreateMutable (alloc, 0, &kCFTypeArrayCallBacks));
35
36    CFReleaser<CFStringRef> sbsFrontAppID (::SBSCopyFrontmostApplicationDisplayIdentifier ());
37    CFReleaser<CFArrayRef> sbsAppIDs (::SBSCopyApplicationDisplayIdentifiers (opt_runningApps, opt_debuggable));
38
39    // Need to check the return value from SBSCopyApplicationDisplayIdentifiers.
40    CFIndex count = sbsAppIDs.get() ? ::CFArrayGetCount (sbsAppIDs.get()) : 0;
41    CFIndex i = 0;
42    for (i = 0; i < count; i++)
43    {
44        CFStringRef displayIdentifier = (CFStringRef)::CFArrayGetValueAtIndex (sbsAppIDs.get(), i);
45
46        // Create a new mutable dictionary for each application
47        CFReleaser<CFMutableDictionaryRef> appInfoDict (::CFDictionaryCreateMutable (alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
48
49        // Get the process id for the app (if there is one)
50        pid_t pid = INVALID_NUB_PROCESS;
51        if (::SBSProcessIDForDisplayIdentifier ((CFStringRef)displayIdentifier, &pid) == true)
52        {
53            CFReleaser<CFNumberRef> pidCFNumber (::CFNumberCreate (alloc,  kCFNumberSInt32Type, &pid));
54            ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PID_KEY, pidCFNumber.get());
55        }
56
57        // Set the a boolean to indicate if this is the front most
58        if (sbsFrontAppID.get() && displayIdentifier && (::CFStringCompare (sbsFrontAppID.get(), displayIdentifier, 0) == kCFCompareEqualTo))
59            ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, kCFBooleanTrue);
60        else
61            ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, kCFBooleanFalse);
62
63
64        CFReleaser<CFStringRef> executablePath (::SBSCopyExecutablePathForDisplayIdentifier (displayIdentifier));
65        if (executablePath.get() != NULL)
66        {
67            ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PATH_KEY, executablePath.get());
68        }
69
70        CFReleaser<CFStringRef> iconImagePath (::SBSCopyIconImagePathForDisplayIdentifier (displayIdentifier)) ;
71        if (iconImagePath.get() != NULL)
72        {
73            ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_ICON_PATH_KEY, iconImagePath.get());
74        }
75
76        CFReleaser<CFStringRef> localizedDisplayName (::SBSCopyLocalizedApplicationNameForDisplayIdentifier (displayIdentifier));
77        if (localizedDisplayName.get() != NULL)
78        {
79            ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_DISPLAY_NAME_KEY, localizedDisplayName.get());
80        }
81
82        // Append the application info to the plist array
83        ::CFArrayAppendValue (plistMutableArray.get(), appInfoDict.get());
84    }
85
86    CFReleaser<CFDataRef> plistData (::CFPropertyListCreateXMLData (alloc, plistMutableArray.get()));
87
88    // write plist to service port
89    if (plistData.get() != NULL)
90    {
91        CFIndex size = ::CFDataGetLength (plistData.get());
92        const UInt8 *bytes = ::CFDataGetBytePtr (plistData.get());
93        if (bytes != NULL && size > 0)
94        {
95            plist.assign((char *)bytes, size);
96            return 0;   // Success
97        }
98        else
99        {
100            DNBLogError("empty application property list.");
101            result = -2;
102        }
103    }
104    else
105    {
106        DNBLogError("serializing task list.");
107        result = -3;
108    }
109
110    return result;
111#else
112    // TODO: list all current processes
113    DNBLogError("SBS doesn't support getting application list.");
114    return -1;
115#endif
116}
117
118
119bool
120IsSBProcess (nub_process_t pid)
121{
122#ifdef WITH_SPRINGBOARD
123    CFReleaser<CFArrayRef> appIdsForPID (::SBSCopyDisplayIdentifiersForProcessID(pid));
124    return appIdsForPID.get() != NULL;
125#else
126    return false;
127#endif
128}
129
130