Back to index

lightning-sunbird  0.9+nobinonly
nsMailMacIntegration.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Mozilla GNOME integration code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * IBM Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2004
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Asaf Romano <mozilla.mano@sent.com>
00024  *   Scott MacGregor <mscott@mozilla.org>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsMailMacIntegration.h"
00041 #include "nsCOMPtr.h"
00042 #include "nsIServiceManager.h"
00043 #include "nsIStringBundle.h"
00044 #include "nsIPromptService.h"
00045 #include "nsIPrefService.h"
00046 #include "nsIPrefBranch.h"
00047 #include "nsString.h"
00048 #include "nsXPIDLString.h"
00049 #include "nsEmbedCID.h"
00050 
00051 // These Launch Services functions are undocumented. We're using them since
00052 // they're the only way to set the default opener for URLs
00053 extern "C" {
00054   // Returns the CFURL for application currently set as the default opener for
00055   // the given URL scheme. appURL must be released by the caller.
00056   extern OSStatus _LSCopyDefaultSchemeHandlerURL(CFStringRef scheme,
00057                                                  CFURLRef *appURL);
00058   extern OSStatus _LSSetDefaultSchemeHandlerURL(CFStringRef scheme,
00059                                                 CFURLRef appURL);
00060   extern OSStatus _LSSaveAndRefresh(void);
00061 }
00062 
00063 NS_IMPL_ISUPPORTS1(nsMailMacIntegration, nsIShellService)
00064 
00065 nsMailMacIntegration::nsMailMacIntegration(): mCheckedThisSession(PR_FALSE)
00066 {}
00067 
00068 NS_IMETHODIMP
00069 nsMailMacIntegration::IsDefaultClient(PRBool aStartupCheck, PRUint16 aApps, PRBool * aIsDefaultClient)
00070 {
00071   *aIsDefaultClient = PR_TRUE;
00072   if (aApps & nsIShellService::MAIL)
00073     *aIsDefaultClient &= isDefaultHandlerForProtocol(CFSTR("mailto"));
00074   if (aApps & nsIShellService::NEWS)
00075     *aIsDefaultClient &= isDefaultHandlerForProtocol(CFSTR("news"));
00076   if (aApps & nsIShellService::RSS)
00077     *aIsDefaultClient &= isDefaultHandlerForProtocol(CFSTR("feed"));
00078   
00079   // if this is the first mail window, maintain internal state that we've
00080   // checked this session (so that subsequent window opens don't show the 
00081   // default client dialog.
00082   
00083   if (aStartupCheck)
00084     mCheckedThisSession = PR_TRUE;
00085   return NS_OK;
00086 }
00087 
00088 NS_IMETHODIMP
00089 nsMailMacIntegration::SetDefaultClient(PRBool aForAllUsers, PRUint16 aApps)
00090 {
00091   nsresult rv = NS_OK;
00092   if (aApps & nsIShellService::MAIL)
00093     rv |= setAsDefaultHandlerForProtocol(CFSTR("mailto"));
00094   if (aApps & nsIShellService::RSS)
00095     rv |= setAsDefaultHandlerForProtocol(CFSTR("news"));
00096   if (aApps & nsIShellService::RSS)
00097     rv |= setAsDefaultHandlerForProtocol(CFSTR("feed"));
00098   
00099   return rv;  
00100 }
00101 
00102 NS_IMETHODIMP
00103 nsMailMacIntegration::GetShouldCheckDefaultClient(PRBool* aResult)
00104 {
00105   if (mCheckedThisSession) 
00106   {
00107     *aResult = PR_FALSE;
00108     return NS_OK;
00109   }
00110 
00111   nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
00112   return prefs->GetBoolPref("mail.shell.checkDefaultClient", aResult);
00113 }
00114 
00115 NS_IMETHODIMP
00116 nsMailMacIntegration::SetShouldCheckDefaultClient(PRBool aShouldCheck)
00117 {
00118   nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
00119   return prefs->SetBoolPref("mail.shell.checkDefaultClient", aShouldCheck);
00120 }
00121 
00122 PRBool
00123 nsMailMacIntegration::isDefaultHandlerForProtocol(CFStringRef aScheme)
00124 {
00125   PRBool isDefault = PR_FALSE;
00126   // Since neither Launch Services nor Internet Config actually differ between 
00127   // bundles which have the same bundle identifier (That is, if we set our
00128   // URL of our bundle as the default handler for the given protocol,
00129   // Launch Service might return the URL of another thunderbird bundle as the
00130   // defualt handler for that protocol), we are comparing the identifiers of the
00131   // bundles rather than their URLs.
00132 
00133   CFStringRef tbirdID = ::CFBundleGetIdentifier(CFBundleGetMainBundle());
00134   if (!tbirdID) {
00135     // CFBundleGetIdentifier is expected to return NULL only if the specified
00136     // bundle doesn't have a bundle identifier in its dictionary. In this case,
00137     // that means a failure, since our bundle does have an identifier.
00138     return isDefault;
00139   }
00140 
00141   ::CFRetain(tbirdID);
00142 
00143   // Get the default handler URL of the given protocol
00144   CFURLRef defaultHandlerURL;
00145   OSStatus err = ::_LSCopyDefaultSchemeHandlerURL(aScheme,
00146                                                   &defaultHandlerURL);
00147 
00148   nsresult rv = NS_ERROR_FAILURE;
00149   if (err == noErr) {
00150     // Get a reference to the bundle (based on its URL)
00151     CFBundleRef defaultHandlerBundle = ::CFBundleCreate(NULL, 
00152                                                         defaultHandlerURL);
00153     if (defaultHandlerBundle) {
00154       CFStringRef defaultHandlerID =
00155         ::CFBundleGetIdentifier(defaultHandlerBundle);
00156       if (defaultHandlerID) {
00157         ::CFRetain(defaultHandlerID);
00158         // and compare it to our bundle identifier
00159         isDefault = ::CFStringCompare(tbirdID, defaultHandlerID, 0)
00160                        == kCFCompareEqualTo;
00161         ::CFRelease(defaultHandlerID);
00162       }
00163       else {
00164         // If the bundle doesn't have an identifier in its info property list,
00165         // it's not our bundle.
00166         isDefault = PR_FALSE;
00167       }
00168 
00169       ::CFRelease(defaultHandlerBundle);
00170     }
00171 
00172     ::CFRelease(defaultHandlerURL);
00173   }
00174   else {
00175     // If |_LSCopyDefaultSchemeHandlerURL| failed, there's no default
00176     // handler for the given protocol
00177     isDefault = PR_FALSE;
00178   }
00179 
00180   ::CFRelease(tbirdID);
00181   return isDefault;
00182 }
00183 
00184 nsresult
00185 nsMailMacIntegration::setAsDefaultHandlerForProtocol(CFStringRef aScheme)
00186 {
00187   CFURLRef tbirdURL = ::CFBundleCopyBundleURL(CFBundleGetMainBundle());
00188 
00189   ::_LSSetDefaultSchemeHandlerURL(aScheme, tbirdURL);
00190   ::_LSSaveAndRefresh();
00191   ::CFRelease(tbirdURL);
00192 
00193   return NS_OK;
00194 }
00195