Back to index

lightning-sunbird  0.9+nobinonly
nsP3PService.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 Platform for Privacy Preferences.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2002
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s): Harish Dhurvasula <harishd@netscape.com>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsP3PService.h"
00039 #include "nsCompactPolicy.h"
00040 #include "nsIServiceManager.h"
00041 #include "nsIHttpChannel.h"
00042 #include "nsIURI.h"
00043 #include "nsIPrefService.h"
00044 #include "nsIPrefBranch.h"
00045 #include "nsIPrefBranch2.h"
00046 #include "nsCRT.h"
00047 
00048 // pref string constants
00049 static const char kCookiesP3PStringPref[] = "network.cookie.p3p";
00050 static const char kCookiesP3PStringDefault[] = "drdraaaa";
00051 
00052 /***********************************
00053  *   nsP3PService Implementation   *
00054  ***********************************/
00055 
00056 NS_IMPL_ISUPPORTS2(nsP3PService, nsICookieConsent, nsIObserver)
00057 
00058 nsP3PService::nsP3PService() 
00059 {
00060   // we can live without a prefservice, so errors here aren't fatal
00061   nsCOMPtr<nsIPrefBranch2> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
00062   if (prefBranch) {
00063     prefBranch->AddObserver(kCookiesP3PStringPref, this, PR_FALSE);
00064   }
00065   PrefChanged(prefBranch);
00066 }
00067 
00068 nsP3PService::~nsP3PService() 
00069 {
00070 }
00071 
00072 void
00073 nsP3PService::PrefChanged(nsIPrefBranch *aPrefBranch)
00074 {
00075   nsresult rv;
00076   if (aPrefBranch) {
00077     rv = aPrefBranch->GetCharPref(kCookiesP3PStringPref, getter_Copies(mCookiesP3PString));
00078   }
00079 
00080   // check for a malformed string, or no prefbranch
00081   if (!aPrefBranch || NS_FAILED(rv) || mCookiesP3PString.Length() != 8) {
00082     // reassign to default string
00083     mCookiesP3PString.AssignLiteral(kCookiesP3PStringDefault);
00084   }
00085 }
00086 
00087 NS_IMETHODIMP
00088 nsP3PService::Observe(nsISupports     *aSubject,
00089                       const char      *aTopic,
00090                       const PRUnichar *aData)
00091 {
00092   nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(aSubject);
00093   NS_ASSERTION(!nsCRT::strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic),
00094                "unexpected topic - we only deal with pref changes!");
00095 
00096   PrefChanged(prefBranch);
00097   return NS_OK;
00098 }
00099 
00100 nsresult
00101 nsP3PService::ProcessResponseHeader(nsIHttpChannel* aHttpChannel) 
00102 {
00103   nsresult result = NS_OK;
00104   
00105   nsCAutoString p3pHeader;
00106   aHttpChannel->GetResponseHeader(NS_LITERAL_CSTRING("P3P"), p3pHeader);
00107 
00108   if (!p3pHeader.IsEmpty()) {
00109     nsCOMPtr<nsIURI> uri;
00110     aHttpChannel->GetURI(getter_AddRefs(uri));
00111       
00112     if (uri) {
00113       if (!mCompactPolicy) {
00114         mCompactPolicy = new nsCompactPolicy();
00115         NS_ENSURE_TRUE(mCompactPolicy,NS_ERROR_OUT_OF_MEMORY);
00116       }
00117 
00118       nsCAutoString spec;
00119       uri->GetSpec(spec);
00120 
00121       result = mCompactPolicy->OnHeaderAvailable(p3pHeader.get(), spec.get());
00122     }
00123   }
00124 
00125   return result;
00126 }
00127 
00128 NS_IMETHODIMP
00129 nsP3PService::GetConsent(nsIURI         *aURI, 
00130                          nsIHttpChannel *aHttpChannel, 
00131                          PRBool          aIsForeign,
00132                          nsCookiePolicy *aPolicy,
00133                          nsCookieStatus *aStatus)
00134 {
00135   *aPolicy = nsICookie::POLICY_UNKNOWN;
00136 
00137   nsCAutoString uriSpec;
00138   nsresult rv = aURI->GetSpec(uriSpec);
00139   NS_ENSURE_SUCCESS(rv, rv);
00140 
00141   if (aHttpChannel) {
00142 #ifdef DEBUG
00143     nsCOMPtr<nsIURI> uri;
00144     aHttpChannel->GetURI(getter_AddRefs(uri));  
00145 
00146     PRBool equals;
00147     NS_ASSERTION(uri && NS_SUCCEEDED(uri->Equals(aURI, &equals)) && equals,
00148                  "URIs don't match");
00149 #endif
00150 
00151     rv = ProcessResponseHeader(aHttpChannel);
00152     NS_ENSURE_SUCCESS(rv, rv);
00153   }
00154 
00155   PRInt32 consent = NS_NO_POLICY;
00156   if (mCompactPolicy) {
00157     mCompactPolicy->GetConsent(uriSpec.get(), consent);
00158   }
00159 
00160   // Map consent to cookies macro
00161   if (consent & NS_NO_POLICY) {
00162     *aPolicy = nsICookie::POLICY_NONE;
00163   }
00164   else if (consent & (NS_NO_CONSENT|NS_INVALID_POLICY)) {
00165     *aPolicy = nsICookie::POLICY_NO_CONSENT;
00166   }
00167   else if (consent & NS_IMPLICIT_CONSENT) {
00168     *aPolicy = nsICookie::POLICY_IMPLICIT_CONSENT;
00169   }
00170   else if (consent & NS_EXPLICIT_CONSENT) {
00171     *aPolicy = nsICookie::POLICY_EXPLICIT_CONSENT;
00172   }
00173   else if (consent & NS_NON_PII_TOKEN) {
00174     *aPolicy = nsICookie::POLICY_NO_II;
00175   }  
00176   else {
00177     NS_WARNING("invalid consent");
00178   }
00179 
00180   // munge the policy into something we can get a status from
00181   nsCookiePolicy policyForStatus = *aPolicy;
00182   if (policyForStatus == nsICookie::POLICY_NO_II) {
00183     // the site does not collect identifiable info - treat it as if it did,
00184     // and asked for explicit consent
00185     policyForStatus = nsICookie::POLICY_EXPLICIT_CONSENT;
00186   }
00187   else if (policyForStatus == nsICookie::POLICY_UNKNOWN) {
00188     // default to no policy
00189     policyForStatus = nsICookie::POLICY_NONE;
00190   }
00191 
00192   // map the policy number into an index for the pref string.
00193   PRInt32 index = (policyForStatus - 1) * 2 + (aIsForeign != PR_FALSE);
00194 
00195   switch (mCookiesP3PString.CharAt(index)) {
00196     case 'a':
00197       *aStatus = nsICookie::STATUS_ACCEPTED;
00198       break;
00199     case 'd':
00200       *aStatus = nsICookie::STATUS_DOWNGRADED;
00201       break;
00202     case 'f':
00203       *aStatus = nsICookie::STATUS_FLAGGED;
00204       break;
00205     case 'r':
00206     default:
00207       *aStatus = nsICookie::STATUS_REJECTED;
00208   }
00209 
00210   return NS_OK;
00211 }