nsMacShellService.cpp
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  * http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  *
15  * The Original Code is Shell Service.
16  *
17  * The Initial Developer of the Original Code is Ben Goodger.
18  * Portions created by the Initial Developer are Copyright (C) 2004
19  * the Initial Developer. All Rights Reserved.
20  *
21  * Contributor(s):
22  * Ben Goodger <ben@mozilla.org> (Original Author)
23  * Asaf Romano <mozilla.mano@sent.com>
24  * Benjamin Smedberg <benjamin@smedbergs.us>
25  *
26  * Alternatively, the contents of this file may be used under the terms of
27  * either the GNU General Public License Version 2 or later (the "GPL"), or
28  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29  * in which case the provisions of the GPL or the LGPL are applicable instead
30  * of those above. If you wish to allow use of your version of this file only
31  * under the terms of either the GPL or the LGPL, and not to allow others to
32  * use your version of this file under the terms of the MPL, indicate your
33  * decision by deleting the provisions above and replace them with the notice
34  * and other provisions required by the GPL or the LGPL. If you do not delete
35  * the provisions above, a recipient may use your version of this file under
36  * the terms of any one of the MPL, the GPL or the LGPL.
37  *
38  * ***** END LICENSE BLOCK ***** */
39 
40 #include "nsDirectoryServiceDefs.h"
41 #include "nsIDOMElement.h"
42 #include "nsIDOMHTMLImageElement.h"
43 #include "nsIImageLoadingContent.h"
44 #include "nsIDocument.h"
45 #include "nsIContent.h"
46 #include "nsILocalFileMac.h"
47 #include "nsIObserverService.h"
48 #include "nsIPrefService.h"
49 #include "nsIServiceManager.h"
50 #include "nsIStringBundle.h"
51 #include "nsIURL.h"
52 #include "nsIWebBrowserPersist.h"
53 #include "nsMacShellService.h"
54 #include "nsNetUtil.h"
55 #include "nsShellService.h"
56 #include "nsStringAPI.h"
57 
58 #include <CoreFoundation/CoreFoundation.h>
59 #include <Carbon/Carbon.h>
60 
61 #define NETWORK_PREFPANE NS_LITERAL_CSTRING("/System/Library/PreferencePanes/Network.prefPane")
62 #define DESKTOP_PREFPANE NS_LITERAL_CSTRING("/System/Library/PreferencePanes/DesktopScreenEffectsPref.prefPane")
63 
64 #define SAFARI_BUNDLE_IDENTIFIER "com.apple.Safari"
65 
67 
68 NS_IMETHODIMP
69 nsMacShellService::IsDefaultBrowser(PRBool aStartupCheck, PRBool* aIsDefaultBrowser)
70 {
71  *aIsDefaultBrowser = PR_FALSE;
72 
73  CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle());
74  if (!firefoxID) {
75  // CFBundleGetIdentifier is expected to return NULL only if the specified
76  // bundle doesn't have a bundle identifier in its plist. In this case, that
77  // means a failure, since our bundle does have an identifier.
78  return NS_ERROR_FAILURE;
79  }
80 
81  // Get the default http handler's bundle ID (or NULL if it has not been explicitly set)
82  CFStringRef defaultBrowserID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("http"));
83  if (defaultBrowserID) {
84  *aIsDefaultBrowser = ::CFStringCompare(firefoxID, defaultBrowserID, 0) == kCFCompareEqualTo;
85  ::CFRelease(defaultBrowserID);
86  }
87 
88  // If this is the first browser window, maintain internal state that we've
89  // checked this session (so that subsequent window opens don't show the
90  // default browser dialog).
91  if (aStartupCheck)
92  mCheckedThisSession = PR_TRUE;
93 
94  return NS_OK;
95 }
96 
97 NS_IMETHODIMP
98 nsMacShellService::SetDefaultBrowser(PRBool aClaimAllTypes, PRBool aForAllUsers)
99 {
100  // Note: We don't support aForAllUsers on Mac OS X.
101 
102  CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle());
103  if (!firefoxID) {
104  return NS_ERROR_FAILURE;
105  }
106 
107  if (::LSSetDefaultHandlerForURLScheme(CFSTR("http"), firefoxID) != noErr) {
108  return NS_ERROR_FAILURE;
109  }
110  if (::LSSetDefaultHandlerForURLScheme(CFSTR("https"), firefoxID) != noErr) {
111  return NS_ERROR_FAILURE;
112  }
113 
114  if (aClaimAllTypes) {
115  if (::LSSetDefaultHandlerForURLScheme(CFSTR("ftp"), firefoxID) != noErr) {
116  return NS_ERROR_FAILURE;
117  }
118  if (::LSSetDefaultRoleHandlerForContentType(kUTTypeHTML, kLSRolesAll, firefoxID) != noErr) {
119  return NS_ERROR_FAILURE;
120  }
121  }
122 
123  return NS_OK;
124 }
125 
126 NS_IMETHODIMP
127 nsMacShellService::GetShouldCheckDefaultBrowser(PRBool* aResult)
128 {
129  // If we've already checked, the browser has been started and this is a
130  // new window open, and we don't want to check again.
131  if (mCheckedThisSession) {
132  *aResult = PR_FALSE;
133  return NS_OK;
134  }
135 
136  nsCOMPtr<nsIPrefBranch> prefs;
137  nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
138  if (pserve)
139  pserve->GetBranch("", getter_AddRefs(prefs));
140 
141  prefs->GetBoolPref(PREF_CHECKDEFAULTBROWSER, aResult);
142 
143  return NS_OK;
144 }
145 
146 NS_IMETHODIMP
147 nsMacShellService::SetShouldCheckDefaultBrowser(PRBool aShouldCheck)
148 {
149  nsCOMPtr<nsIPrefBranch> prefs;
150  nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
151  if (pserve)
152  pserve->GetBranch("", getter_AddRefs(prefs));
153 
154  prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck);
155 
156  return NS_OK;
157 }
158 
159 NS_IMETHODIMP
160 nsMacShellService::SetDesktopBackground(nsIDOMElement* aElement,
161  PRInt32 aPosition)
162 {
163  // Note: We don't support aPosition on OS X.
164 
165  // Get the image URI:
166  nsresult rv;
167  nsCOMPtr<nsIImageLoadingContent> imageContent = do_QueryInterface(aElement,
168  &rv);
169  NS_ENSURE_SUCCESS(rv, rv);
170  nsCOMPtr<nsIURI> imageURI;
171  rv = imageContent->GetCurrentURI(getter_AddRefs(imageURI));
172  NS_ENSURE_SUCCESS(rv, rv);
173 
174  // We need the referer URI for nsIWebBrowserPersist::saveURI
175  nsCOMPtr<nsIContent> content = do_QueryInterface(aElement, &rv);
176  NS_ENSURE_SUCCESS(rv, rv);
177  nsCOMPtr<nsIDocument> doc;
178  doc = content->GetOwnerDoc();
179  if (!doc)
180  return NS_ERROR_FAILURE;
181 
182  nsIURI *docURI = doc->GetDocumentURI();
183  if (!docURI)
184  return NS_ERROR_FAILURE;
185 
186  // Get the desired image file name
187  nsCOMPtr<nsIURL> imageURL(do_QueryInterface(imageURI));
188  if (!imageURL) {
189  // XXXmano (bug 300293): Non-URL images (e.g. the data: protocol) are not
190  // yet supported. What filename should we take here?
191  return NS_ERROR_NOT_IMPLEMENTED;
192  }
193 
194  nsCAutoString fileName;
195  imageURL->GetFileName(fileName);
196  nsCOMPtr<nsIProperties> fileLocator
197  (do_GetService("@mozilla.org/file/directory_service;1", &rv));
198  NS_ENSURE_SUCCESS(rv, rv);
199 
200  // Get the current user's "Pictures" folder (That's ~/Pictures):
201  fileLocator->Get(NS_OSX_PICTURE_DOCUMENTS_DIR, NS_GET_IID(nsILocalFile),
202  getter_AddRefs(mBackgroundFile));
203  if (!mBackgroundFile)
204  return NS_ERROR_OUT_OF_MEMORY;
205 
206  nsAutoString fileNameUnicode;
207  CopyUTF8toUTF16(fileName, fileNameUnicode);
208 
209  // and add the imgage file name itself:
210  mBackgroundFile->Append(fileNameUnicode);
211 
212  // Download the image; the desktop background will be set in OnStateChange()
213  nsCOMPtr<nsIWebBrowserPersist> wbp
214  (do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1", &rv));
215  NS_ENSURE_SUCCESS(rv, rv);
216 
217  PRUint32 flags = nsIWebBrowserPersist::PERSIST_FLAGS_NO_CONVERSION |
218  nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES |
219  nsIWebBrowserPersist::PERSIST_FLAGS_FROM_CACHE;
220 
221  wbp->SetPersistFlags(flags);
222  wbp->SetProgressListener(this);
223 
224  return wbp->SaveURI(imageURI, nsnull, docURI, nsnull, nsnull,
225  mBackgroundFile);
226 }
227 
228 NS_IMETHODIMP
229 nsMacShellService::OnProgressChange(nsIWebProgress* aWebProgress,
230  nsIRequest* aRequest,
231  PRInt32 aCurSelfProgress,
232  PRInt32 aMaxSelfProgress,
233  PRInt32 aCurTotalProgress,
234  PRInt32 aMaxTotalProgress)
235 {
236  return NS_OK;
237 }
238 
239 NS_IMETHODIMP
240 nsMacShellService::OnLocationChange(nsIWebProgress* aWebProgress,
241  nsIRequest* aRequest,
242  nsIURI* aLocation)
243 {
244  return NS_OK;
245 }
246 
247 NS_IMETHODIMP
248 nsMacShellService::OnStatusChange(nsIWebProgress* aWebProgress,
249  nsIRequest* aRequest,
250  nsresult aStatus,
251  const PRUnichar* aMessage)
252 {
253  return NS_OK;
254 }
255 
256 NS_IMETHODIMP
257 nsMacShellService::OnSecurityChange(nsIWebProgress* aWebProgress,
258  nsIRequest* aRequest,
259  PRUint32 aState)
260 {
261  return NS_OK;
262 }
263 
264 NS_IMETHODIMP
265 nsMacShellService::OnStateChange(nsIWebProgress* aWebProgress,
266  nsIRequest* aRequest,
267  PRUint32 aStateFlags,
268  nsresult aStatus)
269 {
270  if (aStateFlags & STATE_STOP) {
271  nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
272  if (os)
273  os->NotifyObservers(nsnull, "shell:desktop-background-changed", nsnull);
274 
275  PRBool exists = PR_FALSE;
276  mBackgroundFile->Exists(&exists);
277  if (!exists)
278  return NS_OK;
279 
280  nsCAutoString nativePath;
281  mBackgroundFile->GetNativePath(nativePath);
282 
283  AEDesc tAEDesc = { typeNull, nil };
284  OSErr err = noErr;
285  AliasHandle aliasHandle = nil;
286  FSRef pictureRef;
287  OSStatus status;
288 
289  // Convert the path into a FSRef
290  status = ::FSPathMakeRef((const UInt8*)nativePath.get(), &pictureRef, NULL);
291  if (status == noErr) {
292  err = ::FSNewAlias(nil, &pictureRef, &aliasHandle);
293  if (err == noErr && aliasHandle == nil)
294  err = paramErr;
295 
296  if (err == noErr) {
297  // We need the descriptor (based on the picture file reference)
298  // for the 'Set Desktop Picture' apple event.
299  char handleState = ::HGetState((Handle)aliasHandle);
300  ::HLock((Handle)aliasHandle);
301  err = ::AECreateDesc(typeAlias, *aliasHandle,
302  GetHandleSize((Handle)aliasHandle), &tAEDesc);
303  // unlock the alias handler
304  ::HSetState((Handle)aliasHandle, handleState);
305  ::DisposeHandle((Handle)aliasHandle);
306  }
307  if (err == noErr) {
308  AppleEvent tAppleEvent;
309  OSType sig = 'MACS';
310  AEBuildError tAEBuildError;
311  // Create a 'Set Desktop Pictue' Apple Event
312  err = ::AEBuildAppleEvent(kAECoreSuite, kAESetData, typeApplSignature,
313  &sig, sizeof(OSType), kAutoGenerateReturnID,
314  kAnyTransactionID, &tAppleEvent, &tAEBuildError,
315  "'----':'obj '{want:type (prop),form:prop" \
316  ",seld:type('dpic'),from:'null'()},data:(@)",
317  &tAEDesc);
318  if (err == noErr) {
319  AppleEvent reply = { typeNull, nil };
320  // Sent the event we built, the reply event isn't necessary
321  err = ::AESend(&tAppleEvent, &reply, kAENoReply, kAENormalPriority,
322  kNoTimeOut, nil, nil);
323  ::AEDisposeDesc(&tAppleEvent);
324  }
325  }
326  }
327  }
328 
329  return NS_OK;
330 }
331 
332 NS_IMETHODIMP
333 nsMacShellService::OpenApplication(PRInt32 aApplication)
334 {
335  nsresult rv = NS_OK;
336  CFURLRef appURL = nil;
337  OSStatus err = noErr;
338 
339  switch (aApplication) {
341  {
342  CFURLRef tempURL = ::CFURLCreateWithString(kCFAllocatorDefault,
343  CFSTR("mailto:"), NULL);
344  err = ::LSGetApplicationForURL(tempURL, kLSRolesAll, NULL, &appURL);
345  ::CFRelease(tempURL);
346  }
347  break;
349  {
350  CFURLRef tempURL = ::CFURLCreateWithString(kCFAllocatorDefault,
351  CFSTR("news:"), NULL);
352  err = ::LSGetApplicationForURL(tempURL, kLSRolesAll, NULL, &appURL);
353  ::CFRelease(tempURL);
354  }
355  break;
357  err = ::LSGetApplicationForInfo('APPL', 'kcmr', NULL, kLSRolesAll, NULL,
358  &appURL);
359  break;
361  {
362  nsCOMPtr<nsILocalFile> lf;
363  rv = NS_NewNativeLocalFile(NETWORK_PREFPANE, PR_TRUE, getter_AddRefs(lf));
364  NS_ENSURE_SUCCESS(rv, rv);
365  PRBool exists;
366  lf->Exists(&exists);
367  if (!exists)
368  return NS_ERROR_FILE_NOT_FOUND;
369  return lf->Launch();
370  }
371  break;
373  {
374  nsCOMPtr<nsILocalFile> lf;
375  rv = NS_NewNativeLocalFile(DESKTOP_PREFPANE, PR_TRUE, getter_AddRefs(lf));
376  NS_ENSURE_SUCCESS(rv, rv);
377  PRBool exists;
378  lf->Exists(&exists);
379  if (!exists)
380  return NS_ERROR_FILE_NOT_FOUND;
381  return lf->Launch();
382  }
383  break;
384  }
385 
386  if (appURL && err == noErr) {
387  err = ::LSOpenCFURLRef(appURL, NULL);
388  rv = err != noErr ? NS_ERROR_FAILURE : NS_OK;
389 
390  ::CFRelease(appURL);
391  }
392 
393  return rv;
394 }
395 
396 NS_IMETHODIMP
397 nsMacShellService::GetDesktopBackgroundColor(PRUint32 *aColor)
398 {
399  // This method and |SetDesktopBackgroundColor| has no meaning on Mac OS X.
400  // The mac desktop preferences UI uses pictures for the few solid colors it
401  // supports.
402  return NS_ERROR_NOT_IMPLEMENTED;
403 }
404 
405 NS_IMETHODIMP
406 nsMacShellService::SetDesktopBackgroundColor(PRUint32 aColor)
407 {
408  // This method and |GetDesktopBackgroundColor| has no meaning on Mac OS X.
409  // The mac desktop preferences UI uses pictures for the few solid colors it
410  // supports.
411  return NS_ERROR_NOT_IMPLEMENTED;
412 }
413 
414 NS_IMETHODIMP
415 nsMacShellService::OpenApplicationWithURI(nsILocalFile* aApplication, const nsACString& aURI)
416 {
417  nsCOMPtr<nsILocalFileMac> lfm(do_QueryInterface(aApplication));
418  CFURLRef appURL;
419  nsresult rv = lfm->GetCFURL(&appURL);
420  if (NS_FAILED(rv))
421  return rv;
422 
423  const nsCString spec(aURI);
424  const UInt8* uriString = (const UInt8*)spec.get();
425  CFURLRef uri = ::CFURLCreateWithBytes(NULL, uriString, aURI.Length(),
426  kCFStringEncodingUTF8, NULL);
427  if (!uri)
428  return NS_ERROR_OUT_OF_MEMORY;
429 
430  CFArrayRef uris = ::CFArrayCreate(NULL, (const void**)&uri, 1, NULL);
431  if (!uris) {
432  ::CFRelease(uri);
433  return NS_ERROR_OUT_OF_MEMORY;
434  }
435 
436  LSLaunchURLSpec launchSpec;
437  launchSpec.appURL = appURL;
438  launchSpec.itemURLs = uris;
439  launchSpec.passThruParams = NULL;
440  launchSpec.launchFlags = kLSLaunchDefaults;
441  launchSpec.asyncRefCon = NULL;
442 
443  OSErr err = ::LSOpenFromURLSpec(&launchSpec, NULL);
444 
445  ::CFRelease(uris);
446  ::CFRelease(uri);
447 
448  return err != noErr ? NS_ERROR_FAILURE : NS_OK;
449 }
450 
451 NS_IMETHODIMP
452 nsMacShellService::GetDefaultFeedReader(nsILocalFile** _retval)
453 {
454  nsresult rv = NS_ERROR_FAILURE;
455  *_retval = nsnull;
456 
457  CFStringRef defaultHandlerID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("feed"));
458  if (!defaultHandlerID) {
459  defaultHandlerID = ::CFStringCreateWithCString(kCFAllocatorDefault,
461  kCFStringEncodingASCII);
462  }
463 
464  CFURLRef defaultHandlerURL = NULL;
465  OSStatus status = ::LSFindApplicationForInfo(kLSUnknownCreator,
466  defaultHandlerID,
467  NULL, // inName
468  NULL, // outAppRef
469  &defaultHandlerURL);
470 
471  if (status == noErr && defaultHandlerURL) {
472  nsCOMPtr<nsILocalFileMac> defaultReader =
473  do_CreateInstance("@mozilla.org/file/local;1", &rv);
474  if (NS_SUCCEEDED(rv)) {
475  rv = defaultReader->InitWithCFURL(defaultHandlerURL);
476  if (NS_SUCCEEDED(rv)) {
477  NS_ADDREF(*_retval = defaultReader);
478  rv = NS_OK;
479  }
480  }
481 
482  ::CFRelease(defaultHandlerURL);
483  }
484 
485  ::CFRelease(defaultHandlerID);
486 
487  return rv;
488 }
return NS_OK
const long APPLICATION_NEWS
const long APPLICATION_MAIL
var uris
const NS_PREFSERVICE_CONTRACTID
function doc() browser.contentDocument
sbDeviceFirmwareAutoCheckForUpdate prototype flags
const long APPLICATION_KEYCHAIN_ACCESS
#define PREF_CHECKDEFAULTBROWSER
#define DESKTOP_PREFPANE
#define NETWORK_PREFPANE
#define SAFARI_BUNDLE_IDENTIFIER
NS_IMPL_ISUPPORTS3(sbLibraryConstraint, sbILibraryConstraint, nsISerializable, nsIClassInfo) NS_IMPL_CI_INTERFACE_GETTER3(sbLibraryConstraint
var os
var uri
Definition: FeedWriter.js:1135
var prefs
Definition: FeedWriter.js:1169
restoreWindow aState