Back to index

lightning-sunbird  0.9+nobinonly
nsMailnewsContentBlocker.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is content blocker code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Michiel van Leeuwen <mvl@exedo.nl>.
00018  * Portions created by the Initial Developer are Copyright (C) 2004
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #include "nsMailnewsContentBlocker.h"
00038 #include "nsIURI.h"
00039 #include "nsIServiceManager.h"
00040 #include "nsIScriptGlobalObject.h"
00041 #include "nsIDOMWindow.h"
00042 #include "nsIDocShellTreeItem.h"
00043 #include "nsIPrefService.h"
00044 #include "nsIPrefBranch.h"
00045 #include "nsIPrefBranch2.h"
00046 #include "nsIDocShell.h"
00047 #include "nsContentPolicyUtils.h"
00048 #include "nsString.h"
00049 #include "nsCRT.h"
00050 
00051 /*
00052  * Block all remote stuff from loading in mailnews. Not only images, but
00053  * also documents, javascripts, iframes etc
00054  * remote is http, https, ftp.
00055  */
00056 
00057 static const char kBlockRemotePrefName[] = "mailnews.message_display.disable_remote_image";
00058 static const PRBool kBlockRemotePrefDefault = PR_FALSE;
00059 
00060 
00061 NS_IMPL_ISUPPORTS3(nsMailnewsContentBlocker, 
00062                    nsIContentPolicy,
00063                    nsIObserver,
00064                    nsSupportsWeakReference)
00065 
00066 nsMailnewsContentBlocker::nsMailnewsContentBlocker()
00067   : mBlockRemotePref(kBlockRemotePrefDefault)
00068 {
00069 }
00070 
00071 nsresult
00072 nsMailnewsContentBlocker::Init()
00073 {
00074   nsCOMPtr<nsIPrefBranch2> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
00075   if (prefBranch) {
00076     prefBranch->AddObserver(kBlockRemotePrefName, this, PR_TRUE);
00077 
00078     PrefChanged(prefBranch, nsnull);
00079   }
00080 
00081   return NS_OK;
00082 }
00083 
00084 void
00085 nsMailnewsContentBlocker::PrefChanged(nsIPrefBranch *aPrefBranch,
00086                                       const char    *aPref)
00087 {
00088   PRInt32 val;
00089 
00090 #define PREF_CHANGED(_P) (!aPref || !strcmp(aPref, _P))
00091 
00092   if (PREF_CHANGED(kBlockRemotePrefName) &&
00093       NS_SUCCEEDED(aPrefBranch->GetBoolPref(kBlockRemotePrefName, &val)))
00094     mBlockRemotePref = val;
00095 }
00096 
00103 static inline already_AddRefed<nsIDocShell>
00104 GetRootDocShell(nsISupports *context)
00105 {
00106   nsIDocShell *docshell = NS_CP_GetDocShellFromContext(context);
00107   if (!docshell)
00108     return nsnull;
00109 
00110   nsresult rv;
00111   nsCOMPtr<nsIDocShellTreeItem> docshellTreeItem(do_QueryInterface(docshell, &rv));
00112   if (NS_FAILED(rv))
00113     return nsnull;
00114 
00115   nsCOMPtr<nsIDocShellTreeItem> rootItem;
00116   // we want the app docshell, so don't use GetSameTypeRootTreeItem
00117   rv = docshellTreeItem->GetRootTreeItem(getter_AddRefs(rootItem));
00118   if (NS_FAILED(rv))
00119     return nsnull;
00120 
00121   nsIDocShell *result;
00122   CallQueryInterface(rootItem, &result);
00123   return result;
00124 }
00125 
00126 // nsIContentPolicy Implementation
00127 NS_IMETHODIMP
00128 nsMailnewsContentBlocker::ShouldLoad(PRUint32          aContentType,
00129                                      nsIURI           *aContentLocation,
00130                                      nsIURI           *aRequestingLocation,
00131                                      nsISupports      *aRequestingContext,
00132                                      const nsACString &aMimeGuess,
00133                                      nsISupports      *aExtra,
00134                                      PRInt16          *aDecision)
00135 {
00136   *aDecision = nsIContentPolicy::ACCEPT;
00137   nsresult rv;
00138 
00139   // we can't do anything without this
00140   if (!aContentLocation)
00141     return NS_OK;
00142 
00143   // Go find out if we are dealing with mailnews. Anything else
00144   // isn't our concern.
00145   nsCOMPtr<nsIDocShell> docshell = GetRootDocShell(aRequestingContext);
00146   if (!docshell)
00147     return NS_OK;
00148 
00149   PRUint32 appType;
00150   rv = docshell->GetAppType(&appType);
00151   // We only want to deal with mailnews
00152   if (NS_FAILED(rv) || appType != nsIDocShell::APP_TYPE_MAIL)
00153     return NS_OK;
00154 
00155   PRBool isFtp;
00156   rv = aContentLocation->SchemeIs("ftp", &isFtp);
00157   NS_ENSURE_SUCCESS(rv,rv);
00158   if (isFtp) {
00159     // never allow ftp for mail messages, 
00160     // because we don't want to send the users email address
00161     // as the anonymous password
00162     *aDecision = nsIContentPolicy::REJECT_REQUEST;
00163     return NS_OK;
00164   }
00165 
00166 
00167   // we only want to check http, https
00168   // for chrome:// and resources and others, no need to check.
00169   nsCAutoString scheme;
00170   aContentLocation->GetScheme(scheme);
00171   if (!scheme.LowerCaseEqualsLiteral("http") &&
00172       !scheme.LowerCaseEqualsLiteral("https"))
00173     return NS_OK;
00174 
00175   // This is mailnews, a protocol we want, now lets do the real work!
00176 
00177   *aDecision = mBlockRemotePref ? nsIContentPolicy::REJECT_REQUEST :
00178                                   nsIContentPolicy::ACCEPT;
00179 
00180   return NS_OK;
00181 }
00182 
00183 NS_IMETHODIMP
00184 nsMailnewsContentBlocker::ShouldProcess(PRUint32          aContentType,
00185                                         nsIURI           *aContentLocation,
00186                                         nsIURI           *aRequestingLocation,
00187                                         nsISupports      *aRequestingContext,
00188                                         const nsACString &aMimeGuess,
00189                                         nsISupports      *aExtra,
00190                                         PRInt16          *aDecision)
00191 {
00192   *aDecision = nsIContentPolicy::ACCEPT;
00193   return NS_OK;
00194 }
00195 
00196 NS_IMETHODIMP
00197 nsMailnewsContentBlocker::Observe(nsISupports     *aSubject,
00198                                   const char      *aTopic,
00199                                   const PRUnichar *aData)
00200 {
00201   nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(aSubject);
00202   NS_ASSERTION(!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic),
00203                "unexpected topic - we only deal with pref changes!");
00204 
00205   if (prefBranch)
00206     PrefChanged(prefBranch, NS_LossyConvertUTF16toASCII(aData).get());
00207   return NS_OK;
00208 }