browser/components/shell/src/nsMacShellService.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsDirectoryServiceDefs.h"
     7 #include "nsIDOMElement.h"
     8 #include "nsIDOMHTMLImageElement.h"
     9 #include "nsIImageLoadingContent.h"
    10 #include "nsIDocument.h"
    11 #include "nsIContent.h"
    12 #include "nsILocalFileMac.h"
    13 #include "nsIObserverService.h"
    14 #include "nsIPrefService.h"
    15 #include "nsIServiceManager.h"
    16 #include "nsIStringBundle.h"
    17 #include "nsIURL.h"
    18 #include "nsIWebBrowserPersist.h"
    19 #include "nsMacShellService.h"
    20 #include "nsNetUtil.h"
    21 #include "nsShellService.h"
    22 #include "nsStringAPI.h"
    23 #include "nsIDocShell.h"
    24 #include "nsILoadContext.h"
    26 #include <CoreFoundation/CoreFoundation.h>
    27 #include <ApplicationServices/ApplicationServices.h>
    29 #define NETWORK_PREFPANE NS_LITERAL_CSTRING("/System/Library/PreferencePanes/Network.prefPane")
    30 #define DESKTOP_PREFPANE NS_LITERAL_CSTRING("/System/Library/PreferencePanes/DesktopScreenEffectsPref.prefPane")
    32 #define SAFARI_BUNDLE_IDENTIFIER "com.apple.Safari"
    34 NS_IMPL_ISUPPORTS(nsMacShellService, nsIMacShellService, nsIShellService, nsIWebProgressListener)
    36 NS_IMETHODIMP
    37 nsMacShellService::IsDefaultBrowser(bool aStartupCheck,
    38                                     bool aForAllTypes,
    39                                     bool* aIsDefaultBrowser)
    40 {
    41   *aIsDefaultBrowser = false;
    43   CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle());
    44   if (!firefoxID) {
    45     // CFBundleGetIdentifier is expected to return nullptr only if the specified
    46     // bundle doesn't have a bundle identifier in its plist. In this case, that
    47     // means a failure, since our bundle does have an identifier.
    48     return NS_ERROR_FAILURE;
    49   }
    51   // Get the default http handler's bundle ID (or nullptr if it has not been
    52   // explicitly set)
    53   CFStringRef defaultBrowserID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("http"));
    54   if (defaultBrowserID) {
    55     *aIsDefaultBrowser = ::CFStringCompare(firefoxID, defaultBrowserID, 0) == kCFCompareEqualTo;
    56     ::CFRelease(defaultBrowserID);
    57   }
    59   // If this is the first browser window, maintain internal state that we've
    60   // checked this session (so that subsequent window opens don't show the 
    61   // default browser dialog).
    62   if (aStartupCheck)
    63     mCheckedThisSession = true;
    65   return NS_OK;
    66 }
    68 NS_IMETHODIMP
    69 nsMacShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers)
    70 {
    71   // Note: We don't support aForAllUsers on Mac OS X.
    73   CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle());
    74   if (!firefoxID) {
    75     return NS_ERROR_FAILURE;
    76   }
    78   if (::LSSetDefaultHandlerForURLScheme(CFSTR("http"), firefoxID) != noErr) {
    79     return NS_ERROR_FAILURE;
    80   }
    81   if (::LSSetDefaultHandlerForURLScheme(CFSTR("https"), firefoxID) != noErr) {
    82     return NS_ERROR_FAILURE;
    83   }
    85   if (aClaimAllTypes) {
    86     if (::LSSetDefaultHandlerForURLScheme(CFSTR("ftp"), firefoxID) != noErr) {
    87       return NS_ERROR_FAILURE;
    88     }
    89     if (::LSSetDefaultRoleHandlerForContentType(kUTTypeHTML, kLSRolesAll, firefoxID) != noErr) {
    90       return NS_ERROR_FAILURE;
    91     }
    92   }
    94   return NS_OK;
    95 }
    97 NS_IMETHODIMP
    98 nsMacShellService::GetShouldCheckDefaultBrowser(bool* aResult)
    99 {
   100   // If we've already checked, the browser has been started and this is a 
   101   // new window open, and we don't want to check again.
   102   if (mCheckedThisSession) {
   103     *aResult = false;
   104     return NS_OK;
   105   }
   107   nsCOMPtr<nsIPrefBranch> prefs;
   108   nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
   109   if (pserve)
   110     pserve->GetBranch("", getter_AddRefs(prefs));
   112   prefs->GetBoolPref(PREF_CHECKDEFAULTBROWSER, aResult);
   114   return NS_OK;
   115 }
   117 NS_IMETHODIMP
   118 nsMacShellService::SetShouldCheckDefaultBrowser(bool aShouldCheck)
   119 {
   120   nsCOMPtr<nsIPrefBranch> prefs;
   121   nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
   122   if (pserve)
   123     pserve->GetBranch("", getter_AddRefs(prefs));
   125   prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck);
   127   return NS_OK;
   128 }
   130 NS_IMETHODIMP
   131 nsMacShellService::GetCanSetDesktopBackground(bool* aResult)
   132 {
   133   *aResult = true;
   134   return NS_OK;
   135 }
   137 NS_IMETHODIMP
   138 nsMacShellService::SetDesktopBackground(nsIDOMElement* aElement, 
   139                                         int32_t aPosition)
   140 {
   141   // Note: We don't support aPosition on OS X.
   143   // Get the image URI:
   144   nsresult rv;
   145   nsCOMPtr<nsIImageLoadingContent> imageContent = do_QueryInterface(aElement,
   146                                                                     &rv);
   147   NS_ENSURE_SUCCESS(rv, rv);
   148   nsCOMPtr<nsIURI> imageURI;
   149   rv = imageContent->GetCurrentURI(getter_AddRefs(imageURI));
   150   NS_ENSURE_SUCCESS(rv, rv);
   152   // We need the referer URI for nsIWebBrowserPersist::saveURI
   153   nsCOMPtr<nsIContent> content = do_QueryInterface(aElement, &rv);
   154   NS_ENSURE_SUCCESS(rv, rv);
   156   nsIURI *docURI = content->OwnerDoc()->GetDocumentURI();
   157   if (!docURI)
   158     return NS_ERROR_FAILURE;
   160   // Get the desired image file name
   161   nsCOMPtr<nsIURL> imageURL(do_QueryInterface(imageURI));
   162   if (!imageURL) {
   163     // XXXmano (bug 300293): Non-URL images (e.g. the data: protocol) are not
   164     // yet supported. What filename should we take here?
   165     return NS_ERROR_NOT_IMPLEMENTED;
   166   }
   168   nsAutoCString fileName;
   169   imageURL->GetFileName(fileName);
   170   nsCOMPtr<nsIProperties> fileLocator
   171     (do_GetService("@mozilla.org/file/directory_service;1", &rv));
   172   NS_ENSURE_SUCCESS(rv, rv);
   174   // Get the current user's "Pictures" folder (That's ~/Pictures):
   175   fileLocator->Get(NS_OSX_PICTURE_DOCUMENTS_DIR, NS_GET_IID(nsIFile),
   176                    getter_AddRefs(mBackgroundFile));
   177   if (!mBackgroundFile)
   178     return NS_ERROR_OUT_OF_MEMORY;
   180   nsAutoString fileNameUnicode;
   181   CopyUTF8toUTF16(fileName, fileNameUnicode);
   183   // and add the imgage file name itself:
   184   mBackgroundFile->Append(fileNameUnicode);
   186   // Download the image; the desktop background will be set in OnStateChange()
   187   nsCOMPtr<nsIWebBrowserPersist> wbp
   188     (do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1", &rv));
   189   NS_ENSURE_SUCCESS(rv, rv);
   191   uint32_t flags = nsIWebBrowserPersist::PERSIST_FLAGS_NO_CONVERSION | 
   192                    nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES |
   193                    nsIWebBrowserPersist::PERSIST_FLAGS_FROM_CACHE;
   195   wbp->SetPersistFlags(flags);
   196   wbp->SetProgressListener(this);
   198   nsCOMPtr<nsILoadContext> loadContext;
   199   nsCOMPtr<nsISupports> container = content->OwnerDoc()->GetContainer();
   200   nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
   201   if (docShell) {
   202     loadContext = do_QueryInterface(docShell);
   203   }
   205   return wbp->SaveURI(imageURI, nullptr, docURI, nullptr, nullptr,
   206                       mBackgroundFile, loadContext);
   207 }
   209 NS_IMETHODIMP
   210 nsMacShellService::OnProgressChange(nsIWebProgress* aWebProgress,
   211                                     nsIRequest* aRequest,
   212                                     int32_t aCurSelfProgress,
   213                                     int32_t aMaxSelfProgress,
   214                                     int32_t aCurTotalProgress,
   215                                     int32_t aMaxTotalProgress)
   216 {
   217   return NS_OK;
   218 }
   220 NS_IMETHODIMP
   221 nsMacShellService::OnLocationChange(nsIWebProgress* aWebProgress,
   222                                     nsIRequest* aRequest,
   223                                     nsIURI* aLocation,
   224                                     uint32_t aFlags)
   225 {
   226   return NS_OK;
   227 }
   229 NS_IMETHODIMP
   230 nsMacShellService::OnStatusChange(nsIWebProgress* aWebProgress,
   231                                   nsIRequest* aRequest,
   232                                   nsresult aStatus,
   233                                   const char16_t* aMessage)
   234 {
   235   return NS_OK;
   236 }
   238 NS_IMETHODIMP
   239 nsMacShellService::OnSecurityChange(nsIWebProgress* aWebProgress,
   240                                     nsIRequest* aRequest,
   241                                     uint32_t aState)
   242 {
   243   return NS_OK;
   244 }
   246 NS_IMETHODIMP
   247 nsMacShellService::OnStateChange(nsIWebProgress* aWebProgress,
   248                                  nsIRequest* aRequest,
   249                                  uint32_t aStateFlags,
   250                                  nsresult aStatus)
   251 {
   252   if (aStateFlags & STATE_STOP) {
   253     nsCOMPtr<nsIObserverService> os(do_GetService("@mozilla.org/observer-service;1"));
   254     if (os)
   255       os->NotifyObservers(nullptr, "shell:desktop-background-changed", nullptr);
   257     bool exists = false;
   258     mBackgroundFile->Exists(&exists);
   259     if (!exists)
   260       return NS_OK;
   262     nsAutoCString nativePath;
   263     mBackgroundFile->GetNativePath(nativePath);
   265     AEDesc tAEDesc = { typeNull, nil };
   266     OSErr err = noErr;
   267     AliasHandle aliasHandle = nil;
   268     FSRef pictureRef;
   269     OSStatus status;
   271     // Convert the path into a FSRef
   272     status = ::FSPathMakeRef((const UInt8*)nativePath.get(), &pictureRef,
   273                              nullptr);
   274     if (status == noErr) {
   275       err = ::FSNewAlias(nil, &pictureRef, &aliasHandle);
   276       if (err == noErr && aliasHandle == nil)
   277         err = paramErr;
   279       if (err == noErr) {
   280         // We need the descriptor (based on the picture file reference)
   281         // for the 'Set Desktop Picture' apple event.
   282         char handleState = ::HGetState((Handle)aliasHandle);
   283         ::HLock((Handle)aliasHandle);
   284         err = ::AECreateDesc(typeAlias, *aliasHandle,
   285                              GetHandleSize((Handle)aliasHandle), &tAEDesc);
   286         // unlock the alias handler
   287         ::HSetState((Handle)aliasHandle, handleState);
   288         ::DisposeHandle((Handle)aliasHandle);
   289       }
   290       if (err == noErr) {
   291         AppleEvent tAppleEvent;
   292         OSType sig = 'MACS';
   293         AEBuildError tAEBuildError;
   294         // Create a 'Set Desktop Pictue' Apple Event
   295         err = ::AEBuildAppleEvent(kAECoreSuite, kAESetData, typeApplSignature,
   296                                   &sig, sizeof(OSType), kAutoGenerateReturnID,
   297                                   kAnyTransactionID, &tAppleEvent, &tAEBuildError,
   298                                   "'----':'obj '{want:type (prop),form:prop" \
   299                                   ",seld:type('dpic'),from:'null'()},data:(@)",
   300                                   &tAEDesc);
   301         if (err == noErr) {
   302           AppleEvent reply = { typeNull, nil };
   303           // Sent the event we built, the reply event isn't necessary
   304           err = ::AESend(&tAppleEvent, &reply, kAENoReply, kAENormalPriority,
   305                          kNoTimeOut, nil, nil);
   306           ::AEDisposeDesc(&tAppleEvent);
   307         }
   308       }
   309     }
   310   }
   312   return NS_OK;
   313 }
   315 NS_IMETHODIMP
   316 nsMacShellService::OpenApplication(int32_t aApplication)
   317 {
   318   nsresult rv = NS_OK;
   319   CFURLRef appURL = nil;
   320   OSStatus err = noErr;
   322   switch (aApplication) {
   323   case nsIShellService::APPLICATION_MAIL:
   324     {
   325       CFURLRef tempURL = ::CFURLCreateWithString(kCFAllocatorDefault,
   326                                                  CFSTR("mailto:"), nullptr);
   327       err = ::LSGetApplicationForURL(tempURL, kLSRolesAll, nullptr, &appURL);
   328       ::CFRelease(tempURL);
   329     }
   330     break;
   331   case nsIShellService::APPLICATION_NEWS:
   332     {
   333       CFURLRef tempURL = ::CFURLCreateWithString(kCFAllocatorDefault,
   334                                                  CFSTR("news:"), nullptr);
   335       err = ::LSGetApplicationForURL(tempURL, kLSRolesAll, nullptr, &appURL);
   336       ::CFRelease(tempURL);
   337     }
   338     break;
   339   case nsIMacShellService::APPLICATION_KEYCHAIN_ACCESS:
   340     err = ::LSGetApplicationForInfo('APPL', 'kcmr', nullptr, kLSRolesAll,
   341                                     nullptr, &appURL);
   342     break;
   343   case nsIMacShellService::APPLICATION_NETWORK:
   344     {
   345       nsCOMPtr<nsIFile> lf;
   346       rv = NS_NewNativeLocalFile(NETWORK_PREFPANE, true, getter_AddRefs(lf));
   347       NS_ENSURE_SUCCESS(rv, rv);
   348       bool exists;
   349       lf->Exists(&exists);
   350       if (!exists)
   351         return NS_ERROR_FILE_NOT_FOUND;
   352       return lf->Launch();
   353     }  
   354     break;
   355   case nsIMacShellService::APPLICATION_DESKTOP:
   356     {
   357       nsCOMPtr<nsIFile> lf;
   358       rv = NS_NewNativeLocalFile(DESKTOP_PREFPANE, true, getter_AddRefs(lf));
   359       NS_ENSURE_SUCCESS(rv, rv);
   360       bool exists;
   361       lf->Exists(&exists);
   362       if (!exists)
   363         return NS_ERROR_FILE_NOT_FOUND;
   364       return lf->Launch();
   365     }  
   366     break;
   367   }
   369   if (appURL && err == noErr) {
   370     err = ::LSOpenCFURLRef(appURL, nullptr);
   371     rv = err != noErr ? NS_ERROR_FAILURE : NS_OK;
   373     ::CFRelease(appURL);
   374   }
   376   return rv;
   377 }
   379 NS_IMETHODIMP
   380 nsMacShellService::GetDesktopBackgroundColor(uint32_t *aColor)
   381 {
   382   // This method and |SetDesktopBackgroundColor| has no meaning on Mac OS X.
   383   // The mac desktop preferences UI uses pictures for the few solid colors it
   384   // supports.
   385   return NS_ERROR_NOT_IMPLEMENTED;
   386 }
   388 NS_IMETHODIMP
   389 nsMacShellService::SetDesktopBackgroundColor(uint32_t aColor)
   390 {
   391   // This method and |GetDesktopBackgroundColor| has no meaning on Mac OS X.
   392   // The mac desktop preferences UI uses pictures for the few solid colors it
   393   // supports.
   394   return NS_ERROR_NOT_IMPLEMENTED;
   395 }
   397 NS_IMETHODIMP
   398 nsMacShellService::OpenApplicationWithURI(nsIFile* aApplication, const nsACString& aURI)
   399 {
   400   nsCOMPtr<nsILocalFileMac> lfm(do_QueryInterface(aApplication));
   401   CFURLRef appURL;
   402   nsresult rv = lfm->GetCFURL(&appURL);
   403   if (NS_FAILED(rv))
   404     return rv;
   406   const nsCString spec(aURI);
   407   const UInt8* uriString = (const UInt8*)spec.get();
   408   CFURLRef uri = ::CFURLCreateWithBytes(nullptr, uriString, aURI.Length(),
   409                                         kCFStringEncodingUTF8, nullptr);
   410   if (!uri) 
   411     return NS_ERROR_OUT_OF_MEMORY;
   413   CFArrayRef uris = ::CFArrayCreate(nullptr, (const void**)&uri, 1, nullptr);
   414   if (!uris) {
   415     ::CFRelease(uri);
   416     return NS_ERROR_OUT_OF_MEMORY;
   417   }
   419   LSLaunchURLSpec launchSpec;
   420   launchSpec.appURL = appURL;
   421   launchSpec.itemURLs = uris;
   422   launchSpec.passThruParams = nullptr;
   423   launchSpec.launchFlags = kLSLaunchDefaults;
   424   launchSpec.asyncRefCon = nullptr;
   426   OSErr err = ::LSOpenFromURLSpec(&launchSpec, nullptr);
   428   ::CFRelease(uris);
   429   ::CFRelease(uri);
   431   return err != noErr ? NS_ERROR_FAILURE : NS_OK;
   432 }
   434 NS_IMETHODIMP
   435 nsMacShellService::GetDefaultFeedReader(nsIFile** _retval)
   436 {
   437   nsresult rv = NS_ERROR_FAILURE;
   438   *_retval = nullptr;
   440   CFStringRef defaultHandlerID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("feed"));
   441   if (!defaultHandlerID) {
   442     defaultHandlerID = ::CFStringCreateWithCString(kCFAllocatorDefault,
   443                                                    SAFARI_BUNDLE_IDENTIFIER,
   444                                                    kCFStringEncodingASCII);
   445   }
   447   CFURLRef defaultHandlerURL = nullptr;
   448   OSStatus status = ::LSFindApplicationForInfo(kLSUnknownCreator,
   449                                                defaultHandlerID,
   450                                                nullptr, // inName
   451                                                nullptr, // outAppRef
   452                                                &defaultHandlerURL);
   454   if (status == noErr && defaultHandlerURL) {
   455     nsCOMPtr<nsILocalFileMac> defaultReader =
   456       do_CreateInstance("@mozilla.org/file/local;1", &rv);
   457     if (NS_SUCCEEDED(rv)) {
   458       rv = defaultReader->InitWithCFURL(defaultHandlerURL);
   459       if (NS_SUCCEEDED(rv)) {
   460         NS_ADDREF(*_retval = defaultReader);
   461         rv = NS_OK;
   462       }
   463     }
   465     ::CFRelease(defaultHandlerURL);
   466   }
   468   ::CFRelease(defaultHandlerID);
   470   return rv;
   471 }

mercurial