From: Robert O'Callahan
Subject: Lockdown feature for Gecko
References:


diff --git a/extensions/cookie/nsCookiePermission.cpp b/extensions/cookie/nsCookiePermission.cpp
--- a/extensions/cookie/nsCookiePermission.cpp
+++ b/extensions/cookie/nsCookiePermission.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:ts=2:sw=2:et: */
+/* vim: set ts=2 sw=2 et: */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -78,16 +78,17 @@ static const PRBool kDefaultPolicy = PR_
 static const char kCookiesLifetimePolicy[] = "network.cookie.lifetimePolicy";
 static const char kCookiesLifetimeDays[] = "network.cookie.lifetime.days";
 static const char kCookiesAlwaysAcceptSession[] = "network.cookie.alwaysAcceptSessionCookies";
 
 static const char kCookiesPrefsMigrated[] = "network.cookie.prefsMigrated";
 // obsolete pref names for migration
 static const char kCookiesLifetimeEnabled[] = "network.cookie.lifetime.enabled";
 static const char kCookiesLifetimeBehavior[] = "network.cookie.lifetime.behavior";
+static const char kCookiesHonorExceptions[] = "network.cookie.honorExceptions";
 static const char kCookiesAskPermission[] = "network.cookie.warnAboutCookies";
 
 static const char kPermissionType[] = "cookie";
 
 #ifdef MOZ_MAIL_NEWS
 // returns PR_TRUE if URI appears to be the URI of a mailnews protocol
 // XXXbz this should be a protocol flag, not a scheme list, dammit!
 static PRBool
@@ -117,16 +118,17 @@ nsCookiePermission::Init()
 
   // failure to access the pref service is non-fatal...
   nsCOMPtr<nsIPrefBranch2> prefBranch =
       do_GetService(NS_PREFSERVICE_CONTRACTID);
   if (prefBranch) {
     prefBranch->AddObserver(kCookiesLifetimePolicy, this, PR_FALSE);
     prefBranch->AddObserver(kCookiesLifetimeDays, this, PR_FALSE);
     prefBranch->AddObserver(kCookiesAlwaysAcceptSession, this, PR_FALSE);
+    prefBranch->AddObserver(kCookiesHonorExceptions, this, PR_FALSE);
     PrefChanged(prefBranch, nsnull);
 
     // migration code for original cookie prefs
     PRBool migrated;
     rv = prefBranch->GetBoolPref(kCookiesPrefsMigrated, &migrated);
     if (NS_FAILED(rv) || !migrated) {
       PRBool warnAboutCookies = PR_FALSE;
       prefBranch->GetBoolPref(kCookiesAskPermission, &warnAboutCookies);
@@ -170,16 +172,20 @@ nsCookiePermission::PrefChanged(nsIPrefB
   if (PREF_CHANGED(kCookiesLifetimeDays) &&
       NS_SUCCEEDED(aPrefBranch->GetIntPref(kCookiesLifetimeDays, &val)))
     // save cookie lifetime in seconds instead of days
     mCookiesLifetimeSec = val * 24 * 60 * 60;
 
   if (PREF_CHANGED(kCookiesAlwaysAcceptSession) &&
       NS_SUCCEEDED(aPrefBranch->GetBoolPref(kCookiesAlwaysAcceptSession, &val)))
     mCookiesAlwaysAcceptSession = val;
+
+  if (PREF_CHANGED(kCookiesHonorExceptions) &&
+      NS_SUCCEEDED(aPrefBranch->GetBoolPref(kCookiesHonorExceptions, &val)))
+    mCookiesHonorExceptions = val;
 }
 
 NS_IMETHODIMP
 nsCookiePermission::SetAccess(nsIURI         *aURI,
                               nsCookieAccess  aAccess)
 {
   //
   // NOTE: nsCookieAccess values conveniently match up with
@@ -199,16 +205,21 @@ nsCookiePermission::CanAccess(nsIURI    
   // it.
   if (IsFromMailNews(aURI)) {
     *aResult = ACCESS_DENY;
     return NS_OK;
   }
 #endif // MOZ_MAIL_NEWS
   
   // finally, check with permission manager...
+  if (!mCookiesHonorExceptions) {
+    *aResult = ACCESS_DEFAULT;
+    return NS_OK;
+  }
+
   nsresult rv = mPermMgr->TestPermission(aURI, kPermissionType, (PRUint32 *) aResult);
   if (NS_SUCCEEDED(rv)) {
     switch (*aResult) {
     // if we have one of the publicly-available values, just return it
     case nsIPermissionManager::UNKNOWN_ACTION: // ACCESS_DEFAULT
     case nsIPermissionManager::ALLOW_ACTION:   // ACCESS_ALLOW
     case nsIPermissionManager::DENY_ACTION:    // ACCESS_DENY
       break;
diff --git a/extensions/cookie/nsCookiePermission.h b/extensions/cookie/nsCookiePermission.h
--- a/extensions/cookie/nsCookiePermission.h
+++ b/extensions/cookie/nsCookiePermission.h
@@ -54,30 +54,32 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICOOKIEPERMISSION
   NS_DECL_NSIOBSERVER
 
   nsCookiePermission() 
     : mCookiesLifetimeSec(LL_MAXINT)
     , mCookiesLifetimePolicy(0) // ACCEPT_NORMALLY
     , mCookiesAlwaysAcceptSession(PR_FALSE)
+    , mCookiesHonorExceptions(PR_TRUE)
     {}
   virtual ~nsCookiePermission() {}
 
   nsresult Init();
   void     PrefChanged(nsIPrefBranch *, const char *);
 
 private:
   PRBool InPrivateBrowsing();
 
   nsCOMPtr<nsIPermissionManager> mPermMgr;
   nsCOMPtr<nsIPrivateBrowsingService> mPBService;
 
   PRInt64      mCookiesLifetimeSec;            // lifetime limit specified in seconds
   PRUint8      mCookiesLifetimePolicy;         // pref for how long cookies are stored
   PRPackedBool mCookiesAlwaysAcceptSession;    // don't prompt for session cookies
+  PRPackedBool mCookiesHonorExceptions;
 };
 
 // {EF565D0A-AB9A-4A13-9160-0644CDFD859A}
 #define NS_COOKIEPERMISSION_CID \
  {0xEF565D0A, 0xAB9A, 0x4A13, {0x91, 0x60, 0x06, 0x44, 0xcd, 0xfd, 0x85, 0x9a }}
 
 #endif
diff --git a/extensions/permissions/nsContentBlocker.cpp b/extensions/permissions/nsContentBlocker.cpp
--- a/extensions/permissions/nsContentBlocker.cpp
+++ b/extensions/permissions/nsContentBlocker.cpp
@@ -71,32 +71,38 @@ static const char *kTypeString[NUMBER_OF
 NS_IMPL_ISUPPORTS3(nsContentBlocker, 
                    nsIContentPolicy,
                    nsIObserver,
                    nsSupportsWeakReference)
 
 nsContentBlocker::nsContentBlocker()
 {
   memset(mBehaviorPref, BEHAVIOR_ACCEPT, NUMBER_OF_TYPES);
+  memset(mHonorExceptions, PR_TRUE, NUMBER_OF_TYPES);
 }
 
 nsresult
 nsContentBlocker::Init()
 {
   nsresult rv;
   mPermissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIPrefService> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIPrefBranch> prefBranch;
   rv = prefService->GetBranch("permissions.default.", getter_AddRefs(prefBranch));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  nsCOMPtr<nsIPrefBranch> honorExceptionsPrefBranch;
+  rv = prefService->GetBranch("permissions.honorExceptions.",
+                              getter_AddRefs(honorExceptionsPrefBranch));
+  NS_ENSURE_SUCCESS(rv, rv);
+
   // Migrate old image blocker pref
   nsCOMPtr<nsIPrefBranch> oldPrefBranch;
   oldPrefBranch = do_QueryInterface(prefService);
   PRInt32 oldPref;
   rv = oldPrefBranch->GetIntPref("network.image.imageBehavior", &oldPref);
   if (NS_SUCCEEDED(rv) && oldPref) {
     PRInt32 newPref;
     switch (oldPref) {
@@ -116,39 +122,49 @@ nsContentBlocker::Init()
 
 
   // The branch is not a copy of the prefservice, but a new object, because
   // it is a non-default branch. Adding obeservers to it will only work if
   // we make sure that the object doesn't die. So, keep a reference to it.
   mPrefBranchInternal = do_QueryInterface(prefBranch, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  mHonorExceptionsPrefBranchInternal =
+    do_QueryInterface(honorExceptionsPrefBranch, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   rv = mPrefBranchInternal->AddObserver("", this, PR_TRUE);
-  PrefChanged(prefBranch, nsnull);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = mHonorExceptionsPrefBranchInternal->AddObserver("", this, PR_TRUE);
+  PrefChanged(nsnull);
 
   return rv;
 }
 
 #undef  LIMIT
 #define LIMIT(x, low, high, default) ((x) >= (low) && (x) <= (high) ? (x) : (default))
 
 void
-nsContentBlocker::PrefChanged(nsIPrefBranch *aPrefBranch,
-                              const char    *aPref)
+nsContentBlocker::PrefChanged(const char *aPref)
 {
-  PRInt32 val;
-
-#define PREF_CHANGED(_P) (!aPref || !strcmp(aPref, _P))
-
-  for(PRUint32 i = 0; i < NUMBER_OF_TYPES; ++i) {
-    if (PREF_CHANGED(kTypeString[i]) &&
-        NS_SUCCEEDED(aPrefBranch->GetIntPref(kTypeString[i], &val)))
-      mBehaviorPref[i] = LIMIT(val, 1, 3, 1);
+  for (PRUint32 i = 0; i < NUMBER_OF_TYPES; ++i) {
+    if (!aPref || !strcmp(kTypeString[i], aPref)) {
+      PRInt32 val;
+      PRBool b;
+      if (mPrefBranchInternal &&
+          NS_SUCCEEDED(mPrefBranchInternal->GetIntPref(kTypeString[i], &val))) {
+        mBehaviorPref[i] = LIMIT(val, 1, 3, 1);
+      }
+      if (mHonorExceptionsPrefBranchInternal &&
+          NS_SUCCEEDED(mHonorExceptionsPrefBranchInternal->GetBoolPref(kTypeString[i], &b))) {
+        mHonorExceptions[i] = b;
+      }
+    }
   }
-
 }
 
 // nsIContentPolicy Implementation
 NS_IMETHODIMP 
 nsContentBlocker::ShouldLoad(PRUint32          aContentType,
                              nsIURI           *aContentLocation,
                              nsIURI           *aRequestingLocation,
                              nsISupports      *aRequestingContext,
@@ -263,21 +279,23 @@ nsContentBlocker::TestPermission(nsIURI 
   // This default will also get used if there is an unknown value in the
   // permission list, or if the permission manager returns unknown values.
   *aPermission = PR_TRUE;
 
   // check the permission list first; if we find an entry, it overrides
   // default prefs.
   // Don't forget the aContentType ranges from 1..8, while the
   // array is indexed 0..7
-  PRUint32 permission;
-  nsresult rv = mPermissionManager->TestPermission(aCurrentURI, 
-                                                   kTypeString[aContentType - 1],
-                                                   &permission);
-  NS_ENSURE_SUCCESS(rv, rv);
+  PRUint32 permission = 0;
+  if (mHonorExceptions[aContentType - 1]) {
+    nsresult rv = mPermissionManager->TestPermission(aCurrentURI,
+                                                     kTypeString[aContentType - 1],
+                                                     &permission);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
 
   // If there is nothing on the list, use the default.
   if (!permission) {
     permission = mBehaviorPref[aContentType - 1];
     *aFromPrefs = PR_TRUE;
   }
 
   // Use the fact that the nsIPermissionManager values map to 
@@ -293,17 +311,17 @@ nsContentBlocker::TestPermission(nsIURI 
   case BEHAVIOR_NOFOREIGN:
     // Third party checking
 
     // Need a requesting uri for third party checks to work.
     if (!aFirstURI)
       return NS_OK;
 
     PRBool trustedSource = PR_FALSE;
-    rv = aFirstURI->SchemeIs("chrome", &trustedSource);
+    nsresult rv = aFirstURI->SchemeIs("chrome", &trustedSource);
     NS_ENSURE_SUCCESS(rv,rv);
     if (!trustedSource) {
       rv = aFirstURI->SchemeIs("resource", &trustedSource);
       NS_ENSURE_SUCCESS(rv,rv);
     }
     if (trustedSource)
       return NS_OK;
 
@@ -359,12 +377,11 @@ nsContentBlocker::TestPermission(nsIURI 
 NS_IMETHODIMP
 nsContentBlocker::Observe(nsISupports     *aSubject,
                           const char      *aTopic,
                           const PRUnichar *aData)
 {
   NS_ASSERTION(!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic),
                "unexpected topic - we only deal with pref changes!");
 
-  if (mPrefBranchInternal)
-    PrefChanged(mPrefBranchInternal, NS_LossyConvertUTF16toASCII(aData).get());
+  PrefChanged(NS_LossyConvertUTF16toASCII(aData).get());
   return NS_OK;
 }
diff --git a/extensions/permissions/nsContentBlocker.h b/extensions/permissions/nsContentBlocker.h
--- a/extensions/permissions/nsContentBlocker.h
+++ b/extensions/permissions/nsContentBlocker.h
@@ -61,26 +61,28 @@ public:
   NS_DECL_NSIOBSERVER
 
   nsContentBlocker();
   nsresult Init();
 
 private:
   ~nsContentBlocker() {}
 
-  void PrefChanged(nsIPrefBranch *, const char *);
+  void PrefChanged(const char *);
   nsresult TestPermission(nsIURI *aCurrentURI,
                           nsIURI *aFirstURI,
                           PRInt32 aContentType,
                           PRBool *aPermission,
                           PRBool *aFromPrefs);
 
   nsCOMPtr<nsIPermissionManager> mPermissionManager;
   nsCOMPtr<nsIPrefBranch2> mPrefBranchInternal;
+  nsCOMPtr<nsIPrefBranch2> mHonorExceptionsPrefBranchInternal;
   PRUint8 mBehaviorPref[NUMBER_OF_TYPES];
+  PRPackedBool mHonorExceptions[NUMBER_OF_TYPES];
 };
 
 #define NS_CONTENTBLOCKER_CID \
 { 0x4ca6b67b, 0x5cc7, 0x4e71, \
   { 0xa9, 0x8a, 0x97, 0xaf, 0x1c, 0x13, 0x48, 0x62 } }
 
 #define NS_CONTENTBLOCKER_CONTRACTID "@mozilla.org/permissions/contentblocker;1"
 
diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -823,16 +823,17 @@ pref("network.automatic-ntlm-auth.truste
 // response to a NTLM challenge.  By default, this is disabled since servers
 // should almost never need the LM hash, and the LM hash is what makes NTLM
 // authentication less secure.  See bug 250691 for further details.
 // NOTE: automatic-ntlm-auth which leverages the OS-provided NTLM
 //       implementation will not be affected by this preference.
 pref("network.ntlm.send-lm-response", false);
 
 pref("permissions.default.image",           1); // 1-Accept, 2-Deny, 3-dontAcceptForeign
+pref("permissions.honorExceptions.image",   true);
 
 #ifndef XP_MACOSX
 #ifdef XP_UNIX
 pref("network.proxy.type",                  5);
 #else
 pref("network.proxy.type",                  0);
 #endif
 #else
@@ -850,16 +851,17 @@ pref("network.proxy.ssl_port",          
 pref("network.proxy.socks",                 "");
 pref("network.proxy.socks_port",            0);
 pref("network.proxy.socks_version",         5);
 pref("network.proxy.socks_remote_dns",      false);
 pref("network.proxy.no_proxies_on",         "localhost, 127.0.0.1");
 pref("network.proxy.failover_timeout",      1800); // 30 minutes
 pref("network.online",                      true); //online/offline
 pref("network.cookie.cookieBehavior",       0); // 0-Accept, 1-dontAcceptForeign, 2-dontUse
+pref("network.cookie.honorExceptions",      true);
 pref("network.cookie.lifetimePolicy",       0); // accept normally, 1-askBeforeAccepting, 2-acceptForSession,3-acceptForNDays
 pref("network.cookie.alwaysAcceptSessionCookies", false);
 pref("network.cookie.prefsMigrated",        false);
 pref("network.cookie.lifetime.days",        90);
 
 // The PAC file to load.  Ignored unless network.proxy.type is 2.
 pref("network.proxy.autoconfig_url", "");
 
diff --git a/xpinstall/src/nsXPInstallManager.cpp b/xpinstall/src/nsXPInstallManager.cpp
--- a/xpinstall/src/nsXPInstallManager.cpp
+++ b/xpinstall/src/nsXPInstallManager.cpp
@@ -300,36 +300,46 @@ nsXPInstallManager::InitManagerInternal(
             packageList[j++] = item->GetSafeURLString();
             packageList[j++] = item->mIconURL.get();
             packageList[j++] = item->mCertName.get();
         }
 
         //-----------------------------------------------------
         // Get permission to install
         //-----------------------------------------------------
+        nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID));
 
 #ifdef ENABLE_SKIN_SIMPLE_INSTALLATION_UI
         if ( mChromeType == CHROME_SKIN )
         {
             // We may want to enable the simple installation UI once
             // bug 343037 is fixed
 
             // skins get a simpler/friendlier dialog
             // XXX currently not embeddable
-            OKtoInstall = ConfirmChromeInstall( mParentWindow, packageList );
+            PRBool themesDisabled = PR_FALSE;
+            if (pref)
+              pref->GetBoolPref("config.lockdown.disable_themes", &themesDisabled);
+            OKtoInstall = !themesDisabled &&
+              ConfirmChromeInstall( mParentWindow, packageList );
         }
         else
         {
 #endif
+          PRBool extensionsDisabled = PR_FALSE;
+          if (pref)
+            pref->GetBoolPref("config.lockdown.disable_extensions", &extensionsDisabled);
+          if (!extensionsDisabled) {
             rv = dlgSvc->ConfirmInstall( mParentWindow,
                                          packageList,
                                          numStrings,
                                          &OKtoInstall );
             if (NS_FAILED(rv))
                 OKtoInstall = PR_FALSE;
+          }
 #ifdef ENABLE_SKIN_SIMPLE_INSTALLATION_UI
         }
 #endif
 
         if (OKtoInstall)
         {
             //-----------------------------------------------------
             // Open the progress dialog
