diff --git a/extensions/cookie/MANIFEST_IDL b/extensions/cookie/MANIFEST_IDL index bd0b0599c52f..99bfde99a604 100644 --- a/extensions/cookie/MANIFEST_IDL +++ b/extensions/cookie/MANIFEST_IDL @@ -6,3 +6,4 @@ nsIPermissionManager.idl nsICookieConsent.idl nsICookieAcceptDialog.idl nsICookiePromptService.idl +nsICookiePermission.idl diff --git a/extensions/cookie/Makefile.in b/extensions/cookie/Makefile.in index 2bcd85857a93..2653c2c466cd 100644 --- a/extensions/cookie/Makefile.in +++ b/extensions/cookie/Makefile.in @@ -61,11 +61,10 @@ CPPSRCS = \ nsPermissionManager.cpp \ nsPopupWindowManager.cpp \ nsCookies.cpp \ - nsImages.cpp \ - nsPermissions.cpp \ nsUtils.cpp \ nsCookieHTTPNotify.cpp \ nsCookiePromptService.cpp \ + nsCookiePermission.cpp \ $(NULL) SDK_XPIDLSRCS = \ @@ -81,6 +80,7 @@ XPIDLSRCS = \ nsICookieAcceptDialog.idl \ nsICookiePromptService.idl \ nsICookieManager2.idl \ + nsICookiePermission.idl \ $(NULL) EXPORTS = \ diff --git a/extensions/cookie/macbuild/cookie.xml b/extensions/cookie/macbuild/cookie.xml index 46a7fd201aa8..b889db9c1131 100644 --- a/extensions/cookie/macbuild/cookie.xml +++ b/extensions/cookie/macbuild/cookie.xml @@ -1006,13 +1006,6 @@ Text Debug - - Name - nsImages.cpp - MacOS - Text - Debug - Name nsImgManager.cpp @@ -1057,7 +1050,7 @@ Name - nsPermissions.cpp + nsCookiePermission.cpp MacOS Text Debug @@ -1126,11 +1119,6 @@ nsCookies.cpp MacOS - - Name - nsImages.cpp - MacOS - Name nsImgManager.cpp @@ -1163,7 +1151,7 @@ Name - nsPermissions.cpp + nsCookiePermission.cpp MacOS @@ -2126,13 +2114,6 @@ Text Debug - - Name - nsImages.cpp - MacOS - Text - Debug - Name nsImgManager.cpp @@ -2177,7 +2158,7 @@ Name - nsPermissions.cpp + nsCookiePermission.cpp MacOS Text Debug @@ -2246,11 +2227,6 @@ nsCookies.cpp MacOS - - Name - nsImages.cpp - MacOS - Name nsImgManager.cpp @@ -2283,7 +2259,7 @@ Name - nsPermissions.cpp + nsCookiePermission.cpp MacOS @@ -2332,12 +2308,6 @@ nsCookieService.cpp MacOS - - Cookie.shlb - Name - nsImages.cpp - MacOS - Cookie.shlb Name @@ -2377,7 +2347,7 @@ Cookie.shlb Name - nsPermissions.cpp + nsCookiePermission.cpp MacOS diff --git a/extensions/cookie/macbuild/cookieIDL.xml b/extensions/cookie/macbuild/cookieIDL.xml index 36e1eef9a380..907620f97aa0 100644 --- a/extensions/cookie/macbuild/cookieIDL.xml +++ b/extensions/cookie/macbuild/cookieIDL.xml @@ -776,6 +776,13 @@ Text + + Name + nsICookiePermission.idl + MacOS + Text + + Name nsICookiePromptService.idl @@ -832,6 +839,11 @@ nsIPermissionManager.idl MacOS + + Name + nsICookiePermission.idl + MacOS + Name nsICookiePromptService.idl @@ -1567,6 +1579,13 @@ Text + + Name + nsICookiePermission.idl + MacOS + Text + + Name nsICookiePromptService.idl @@ -1623,6 +1642,11 @@ nsIPermissionManager.idl MacOS + + Name + nsICookiePermission.idl + MacOS + Name nsICookiePromptService.idl @@ -1691,6 +1715,12 @@ nsIPermissionManager.idl MacOS + + headers + Name + nsICookiePermission.idl + MacOS + headers Name diff --git a/extensions/cookie/nsCookiePermission.cpp b/extensions/cookie/nsCookiePermission.cpp new file mode 100644 index 000000000000..48e592a25451 --- /dev/null +++ b/extensions/cookie/nsCookiePermission.cpp @@ -0,0 +1,122 @@ +/* ***** 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/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is cookie manager code. + * + * The Initial Developer of the Original Code is + * Michiel van Leeuwen (mvl@exedo.nl). + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +#include "nsCookiePermission.h" +#include "nsCookie.h" +#include "nsICookieAcceptDialog.h" +#include "nsIWindowWatcher.h" +#include "nsIServiceManager.h" +#include "nsString.h" +#include "nsIDialogParamBlock.h" +#include "nsArray.h" +#include "nsCookiePromptService.h" + +/**************************************************************** + ************************ nsCookiePermission ******************** + ****************************************************************/ + +static const PRUint32 kDefaultPolicy = nsIPermissionManager::ALLOW_ACTION; + +NS_IMPL_ISUPPORTS1(nsCookiePermission, nsICookiePermission); + +nsCookiePermission::nsCookiePermission() + : mPermissionManager(nsnull) +{ +} + +nsCookiePermission::~nsCookiePermission() +{ +} + +nsresult +nsCookiePermission::Init() +{ + // Continue on an error. We can do a few things without a permission manager + mPermissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); + + return NS_OK; +} + +NS_IMETHODIMP +nsCookiePermission::TestPermission(nsIURI *aURI, + nsICookie *aCookie, + nsIDOMWindow *aParent, + PRInt32 aCookiesFromHost, + PRBool aChangingCookie, + PRBool aShowDialog, + PRBool *aPermission) +{ + NS_ASSERTION(aURI, "could not get uri"); + + nsresult rv; + *aPermission = kDefaultPolicy; + + nsCAutoString hostPort; + aURI->GetHostPort(hostPort); + if (hostPort.IsEmpty()) + return NS_OK; + + PRUint32 listPermission = nsIPermissionManager::UNKNOWN_ACTION; + if (mPermissionManager) { + mPermissionManager->TestPermission(aURI, nsIPermissionManager::COOKIE_TYPE, &listPermission); + } + + if (listPermission == nsIPermissionManager::UNKNOWN_ACTION) { + if (aShowDialog && aCookie) { + // we don't cache the cookiePromptService - it's not used often, so not worth the memory + nsCOMPtr cookiePromptService = do_GetService(NS_COOKIEPROMPTSERVICE_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + + PRBool rememberDecision = PR_FALSE; + + rv = cookiePromptService-> + CookieDialog(nsnull, aCookie, hostPort, + aCookiesFromHost, aChangingCookie, &rememberDecision, + aPermission); + if (NS_FAILED(rv)) return rv; + + if (rememberDecision && mPermissionManager) { + // Remember this decision + mPermissionManager->Add(aURI, nsIPermissionManager::COOKIE_TYPE, *aPermission); + } + } + } else { + *aPermission = (listPermission == nsIPermissionManager::ALLOW_ACTION); + } + + return NS_OK; +} diff --git a/extensions/cookie/nsCookiePermission.h b/extensions/cookie/nsCookiePermission.h new file mode 100644 index 000000000000..41ba4f21c036 --- /dev/null +++ b/extensions/cookie/nsCookiePermission.h @@ -0,0 +1,65 @@ +/* ***** 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/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is cookie manager code. + * + * The Initial Developer of the Original Code is + * Michiel van Leeuwen (mvl@exedo.nl). + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsCookiePermission_h__ +#define nsCookiePermission_h__ + +#include "nsICookiePermission.h" +#include "nsIDOMWindow.h" +#include "nsCOMPtr.h" +#include "nsIPermissionManager.h" + +#include "nsIURI.h" + +class nsCookiePermission : public nsICookiePermission +{ +public: + nsCookiePermission(); + virtual ~nsCookiePermission(); + nsresult Init(); + + NS_DECL_ISUPPORTS + NS_DECL_NSICOOKIEPERMISSION + +private: + nsCOMPtr mPermissionManager; +}; + +// {CE002B28-92B7-4701-8621-CC925866FB87} +#define NS_COOKIEPERMISSION_CID \ + {0xEF565D0A, 0xAB9A, 0x4A13, {0x91, 0x60, 0x06, 0x44, 0xcd, 0xfd, 0x85, 0x9a }} + +#endif diff --git a/extensions/cookie/nsCookiePromptService.cpp b/extensions/cookie/nsCookiePromptService.cpp index d475d2bbba53..222b8a9d4ed9 100644 --- a/extensions/cookie/nsCookiePromptService.cpp +++ b/extensions/cookie/nsCookiePromptService.cpp @@ -63,7 +63,7 @@ nsCookiePromptService::CookieDialog(nsIDOMWindow *aParent, const nsACString &aHostname, PRInt32 aCookiesFromHost, PRBool aChangingCookie, - PRBool *aCheckValue, + PRBool *aRememberDecision, PRBool *aAccept) { nsresult rv; @@ -74,7 +74,6 @@ nsCookiePromptService::CookieDialog(nsIDOMWindow *aParent, // since we're setting PRInt32's here, we have to sanitize the PRBool's first. // (myBool != PR_FALSE) is guaranteed to return either 1 or 0. block->SetInt(nsICookieAcceptDialog::ACCEPT_COOKIE, 1); - block->SetInt(nsICookieAcceptDialog::REMEMBER_DECISION, *aCheckValue != PR_FALSE); block->SetString(nsICookieAcceptDialog::HOSTNAME, NS_ConvertUTF8toUCS2(aHostname).get()); block->SetInt(nsICookieAcceptDialog::COOKIESFROMHOST, aCookiesFromHost); block->SetInt(nsICookieAcceptDialog::CHANGINGCOOKIE, aChangingCookie != PR_FALSE); @@ -111,7 +110,7 @@ nsCookiePromptService::CookieDialog(nsIDOMWindow *aParent, *aAccept = (tempValue == 1); block->GetInt(nsICookieAcceptDialog::REMEMBER_DECISION, &tempValue); - *aCheckValue = (tempValue == 1); + *aRememberDecision = (tempValue == 1); return rv; } diff --git a/extensions/cookie/nsCookieService.h b/extensions/cookie/nsCookieService.h index 97c5f6cf4f46..6ce54ecc24de 100644 --- a/extensions/cookie/nsCookieService.h +++ b/extensions/cookie/nsCookieService.h @@ -49,11 +49,19 @@ #include "nsIObserverService.h" #include "nsIPrefBranch.h" #include "nsIPrefBranchInternal.h" -#include "nsPermissions.h" +#include "nsXPIDLString.h" //////////////////////////////////////////////////////////////////////////////// // nsCookiePrefObserver +// enumerated type, used to specify default cookie behavior +typedef enum { + PERMISSION_Accept, + PERMISSION_DontAcceptForeign, + PERMISSION_DontUse, + PERMISSION_P3P +} PERMISSION_BehaviorEnum; + class nsCookiePrefObserver : public nsIObserver , public nsSupportsWeakReference { diff --git a/extensions/cookie/nsCookies.cpp b/extensions/cookie/nsCookies.cpp index 0d6ce028dc06..98e1515a5872 100644 --- a/extensions/cookie/nsCookies.cpp +++ b/extensions/cookie/nsCookies.cpp @@ -40,7 +40,8 @@ #include "nsCookies.h" #include "nsCookieService.h" -#include "nsPermissions.h" +#include "nsICookiePermission.h" +#include "nsIPermissionManager.h" #include "nsIIOService.h" #include "prprf.h" #include "nsReadableUtils.h" @@ -681,18 +682,27 @@ COOKIE_Remove(const nsACString &host, if (cookieInList->path.Equals(path) && cookieInList->host.Equals(host) && cookieInList->name.Equals(name)) { - // check if we need to add the host to the permissions blacklist - if (blocked && NS_SUCCEEDED(PERMISSION_Read())) { - // remove leading dot from host - // we need this trickery since Permission_AddHost wants an nsAFlatCString - // (and we want to avoid PromiseFlatCString()). - // we should push this portion into the UI, it shouldn't live here in the backend. - nsDependentCString hostWithoutDot(cookieInList->host.get(), cookieInList->host.Length()); - if (!cookieInList->host.IsEmpty() && cookieInList->host.First() == '.') { - hostWithoutDot.Rebind(cookieInList->host.get() + 1, cookieInList->host.Length() - 1); + // check if we need to add the host to the permissions blacklist. + // we should push this portion into the UI, it shouldn't live here in the backend. + if (blocked) { + nsresult rv; + nsCOMPtr permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv); + + if (NS_SUCCEEDED(rv)) { + nsCOMPtr uri; + NS_NAMED_LITERAL_CSTRING(httpPrefix, "http://"); + // remove leading dot from host + if (!cookieInList->host.IsEmpty() && cookieInList->host.First() == '.') { + rv = NS_NewURI(getter_AddRefs(uri), PromiseFlatCString(httpPrefix + Substring(cookieInList->host, 1, cookieInList->host.Length() - 1))); + } else { + rv = NS_NewURI(getter_AddRefs(uri), PromiseFlatCString(httpPrefix + cookieInList->host)); + } + + if (NS_SUCCEEDED(rv)) + permissionManager->Add(uri, + nsIPermissionManager::COOKIE_TYPE, + nsIPermissionManager::DENY_ACTION); } - - Permission_AddHost(hostWithoutDot, PR_FALSE, COOKIEPERMISSION, PR_TRUE); } sCookieList->RemoveElementAt(i); @@ -1653,12 +1663,12 @@ COOKIE_ChangeFormat(cookie_CookieStruct *aCookie) // to be processed PRIVATE PRBool cookie_SetCookieInternal(nsIURI *aHostURI, - nsIPrompt *aPrompt, nsDependentCString &aCookieHeader, nsInt64 aServerTime, nsCookieStatus aStatus, nsCookiePolicy aPolicy) { + nsresult rv; // keep a |const char*| version of the unmodified aCookieHeader, // for logging purposes const char *cookieHeader = aCookieHeader.get(); @@ -1666,6 +1676,9 @@ cookie_SetCookieInternal(nsIURI *aHostURI, nsInt64 expiryTime, currentTime = nsTime() / PR_USEC_PER_SEC; PRBool isSession, foundCookie; + nsCOMPtr thisCookie; + nsCOMPtr cookiePermission; + // cookie stores all the attributes parsed from the cookie; // expires and maxage are separate, because we have to process them to find the expiry. // create a new cookie to store the attributes @@ -1723,23 +1736,29 @@ cookie_SetCookieInternal(nsIURI *aHostURI, goto failure; } + // create a new nsICookie and copy the cookie data, + // for passing to the permission manager + thisCookie = COOKIE_ChangeFormat(cookie); + + // we want to cache this ptr when we merge everything into nsCookieService + cookiePermission = do_GetService(NS_COOKIEPERMISSION_CONTRACTID, &rv); // check permissions from site permission list, or ask the user, // to determine if we can set the cookie - if (NS_SUCCEEDED(PERMISSION_Read())) { - // create a new nsICookie and copy the cookie data - nsCOMPtr thisCookie = COOKIE_ChangeFormat(cookie); - - if (!thisCookie || - !Permission_Check(aPrompt, cookie->host.get(), COOKIEPERMISSION, - gCookiePrefObserver->mCookiesAskPermission, - thisCookie, countFromHost, foundCookie)) { + if (NS_SUCCEEDED(rv)) { + PRBool permission; + // we need to think about prompters/parent windows here - TestPermission + // needs one to prompt, so right now it has to fend for itself to get one + rv = cookiePermission->TestPermission(aHostURI, thisCookie, nsnull, + countFromHost, foundCookie, + gCookiePrefObserver->mCookiesAskPermission, + &permission); + if (!permission) { COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, cookieHeader, "cookies are blocked for this site"); goto failure; } } // add the cookie to the list - nsresult rv; rv = COOKIE_Add(cookie, nsTime() / PR_USEC_PER_SEC, aHostURI, cookieHeader); if (NS_FAILED(rv)) { // no need to log a failure here, Add() does it for us @@ -1809,7 +1828,7 @@ COOKIE_SetCookie(nsIURI *aHostURI, // switch to a nice string type now, and process each cookie in the header nsDependentCString cookieHeader(aCookieHeader); - while (cookie_SetCookieInternal(aHostURI, aPrompt, + while (cookie_SetCookieInternal(aHostURI, cookieHeader, serverTime, cookieStatus, cookiePolicy)); } diff --git a/extensions/cookie/nsICookiePermission.idl b/extensions/cookie/nsICookiePermission.idl new file mode 100644 index 000000000000..e0f582fd0b47 --- /dev/null +++ b/extensions/cookie/nsICookiePermission.idl @@ -0,0 +1,70 @@ +/* ***** 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/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is cookie manager code. + * + * The Initial Developer of the Original Code is + * Michiel van Leeuwen (mvl@exedo.nl). + * Portions created by the Initial Developer are Copyright (C) 2003 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +/** + * An interface to test for cookie permissions + */ + +interface nsICookie; +interface nsIURI; +interface nsIDOMWindow; + +[scriptable, uuid(EF565D0A-AB9A-4A13-9160-0644CDFD859A)] +interface nsICookiePermission : nsISupports +{ + /** + * Test if a cookie from the given host should be accepted or denied + * @param uri the website to be tested + * @param cookie the cookie that wants to be set + * @param parent the parant window + * @param cookiesFromHost number of cookies this host already has set + * @param changingCookie are we changing this cookie? + * @param showDialog show a prompt to the user? + * @return whether the cookie has permission to be loaded + */ + boolean testPermission(in nsIURI uri, + in nsICookie cookie, + in nsIDOMWindow parent, + in long cookiesFromHost, + in boolean changingCookie, + in boolean showDialog); +}; + +%{ C++ +#define NS_COOKIEPERMISSION_CONTRACTID "@mozilla.org/cookie/permission;1" +%} diff --git a/extensions/cookie/nsICookiePromptService.idl b/extensions/cookie/nsICookiePromptService.idl index 6a448f054de0..0ec087207055 100644 --- a/extensions/cookie/nsICookiePromptService.idl +++ b/extensions/cookie/nsICookiePromptService.idl @@ -65,7 +65,7 @@ interface nsICookiePromptService : nsISupports in ACString hostname, in long cookiesFromHost, in boolean changingCookie, - inout boolean checkValue); + out boolean rememberDecision); }; %{C++ diff --git a/extensions/cookie/nsIImgManager.idl b/extensions/cookie/nsIImgManager.idl index 0b716326ecf3..b2dad944c0d9 100644 --- a/extensions/cookie/nsIImgManager.idl +++ b/extensions/cookie/nsIImgManager.idl @@ -36,10 +36,9 @@ * * ***** END LICENSE BLOCK ***** */ -/* - - This file contains an interface to the Image Manager. - +/** + * This file contains an interface to the Image Manager, + * used for blocking images from user-specified sites. */ #include "nsISupports.idl" @@ -49,12 +48,16 @@ interface nsIURI; [scriptable, uuid(D60B3710-166D-11d5-A542-0010A401EB10)] interface nsIImgManager : nsISupports { - void block(in nsIURI imageURL); + /** + * Test if the given image from URI can be loaded + * @param uri the uri of the image which wants to be loaded + * @param firstUri the uri of the document which tried to load the image + * @return whether the image has permission to be loaded + */ + boolean testPermission(in nsIURI uri, + in nsIURI firstUri); }; %{ C++ -// {D60B3710-166D-11d5-A542-0010A401EB10} -#define NS_IMGMANAGER_CID \ -{ 0xd60b3710, 0x166d, 0x11d5, { 0xa5, 0x42, 0x0, 0x10, 0xa4, 0x1, 0xeb, 0x10 } } #define NS_IMGMANAGER_CONTRACTID "@mozilla.org/imgmanager;1" %} diff --git a/extensions/cookie/nsIPermission.idl b/extensions/cookie/nsIPermission.idl index 74f22d1e212f..8ebf10e3b711 100644 --- a/extensions/cookie/nsIPermission.idl +++ b/extensions/cookie/nsIPermission.idl @@ -24,24 +24,30 @@ [scriptable, uuid(28F16D80-157B-11d5-A542-0010A401EB10)] /** - This interface represents a "permission" object. -*/ + * This interface defines a "permission" object, + * used to specify allowed/blocked objects from + * user-specified sites (cookies, images etc). + */ -interface nsIPermission : nsISupports { +interface nsIPermission : nsISupports +{ + /** + * The name of the host for which the permission is set + */ + readonly attribute AUTF8String host; - /* the name of the host */ - readonly attribute string host; + /** + * The type of permission (e.g., cookie, image, etc) + * (see nsIPermissionManager.idl for allowed values) + */ + readonly attribute PRUint32 type; - /* the type of permission (e.g., cookie, image, etc) */ - readonly attribute PRInt32 type; - - /* the permission */ - readonly attribute boolean capability; + /** + * The permission (see nsIPermissionManager.idl for allowed values) + */ + readonly attribute PRUint32 capability; }; %{ C++ -// {28F16D80-157B-11d5-A542-0010A401EB10} -#define NS_PERMISSION_CID \ -{ 0x28f16d80, 0x157b, 0x11d5, { 0xa5, 0x42, 0x0, 0x10, 0xa4, 0x1, 0xeb, 0x10 } } #define NS_PERMISSION_CONTRACTID "@mozilla.org/permission;1" %} diff --git a/extensions/cookie/nsIPermissionManager.idl b/extensions/cookie/nsIPermissionManager.idl index de0ecd660d24..9ef54be3fd3b 100644 --- a/extensions/cookie/nsIPermissionManager.idl +++ b/extensions/cookie/nsIPermissionManager.idl @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: NPL 1.1/GPL 2.0/LGPL 2.1 * @@ -36,28 +36,81 @@ * * ***** END LICENSE BLOCK ***** */ -/* - - This file contains an interface to the Permission Manager. - +/** + * This file contains an interface to the Permission Manager, + * used for blocking objects (cookies, images etc) from + * used-defined sites + * + * This service broadcasts a PERM_CHANGE_NOTIFICATION notification + * when any permission changes. You can add yourself as an observer. */ #include "nsISupports.idl" #include "nsISimpleEnumerator.idl" +interface nsIURI; +interface nsIObserver; + [scriptable, uuid(4F6B5E00-0C36-11d5-A535-0010A401EB10)] interface nsIPermissionManager : nsISupports { - void add(in AUTF8String objectURL, in boolean permission, in PRInt32 type); - boolean testForBlocking(in AUTF8String objectURL, in PRInt32 type); + /** + * Allowed return values from the testPermission method + */ + const PRUint32 UNKNOWN_ACTION = 0; + const PRUint32 ALLOW_ACTION = 1; + const PRUint32 DENY_ACTION = 2; + + /** + * These values are the different types of permissions supported + */ + const PRUint32 COOKIE_TYPE = 0; + const PRUint32 IMAGE_TYPE = 1; + const PRUint32 POPUP_TYPE = 2; + + /** + * Add permission information for a given URI and permission type. + * @param uri is the website to add the permission for + * @param permission is one of the enumerated permission actions above + * @param type is one of the enumerated permission types above + */ + void add(in nsIURI uri, + in PRUint32 type, + in PRUint32 permission); + + /** + * Remove permission information for a given URI and permission type. + * Note that this method takes a host string, not an nsIURI. + * @param host is the host to remove the permission for + * @param type is one of the enumerated permission types above + */ + void remove(in AUTF8String host, + in PRUint32 type); + + /** + * Clear permission information for all websites. + */ void removeAll(); + + /** + * Test whether a website has permission to perform the given action. + * @param uri the website to be tested + * @param type one of the enumerated types above + * @return one of the enumerated permission actions above + */ + PRUint32 testPermission(in nsIURI uri, + in PRUint32 type); + + /** + * Allows enumeration of all stored permissions + * @return an nsISimpleEnumerator interface that allows access to + * nsIPermission objects + */ readonly attribute nsISimpleEnumerator enumerator; - void remove(in AUTF8String host, in PRInt32 type); }; %{ C++ -// {4F6B5E00-0C36-11d5-A535-0010A401EB10} -#define NS_PERMISSIONMANAGER_CID \ -{ 0x4f6b5e00, 0xc36, 0x11d5, { 0xa5, 0x35, 0x0, 0x10, 0xa4, 0x1, 0xeb, 0x10 } } #define NS_PERMISSIONMANAGER_CONTRACTID "@mozilla.org/permissionmanager;1" + +#define PERM_CHANGE_NOTIFICATION "perm-changed" %} diff --git a/extensions/cookie/nsImgManager.cpp b/extensions/cookie/nsImgManager.cpp index 5f0e41d2e0dc..6b624e5fe6c2 100644 --- a/extensions/cookie/nsImgManager.cpp +++ b/extensions/cookie/nsImgManager.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: NPL 1.1/GPL 2.0/LGPL 2.1 * @@ -37,7 +37,6 @@ * ***** END LICENSE BLOCK ***** */ #include "nsImgManager.h" -#include "nsImages.h" #include "nsIDocument.h" #include "nsIContent.h" #include "nsCOMPtr.h" @@ -48,122 +47,295 @@ #include "nsIScriptGlobalObject.h" #include "nsIDOMWindow.h" #include "nsIDocShellTreeItem.h" +#include "nsCRT.h" +#include "nsIPrefBranchInternal.h" +#include "nsIObserverService.h" static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); +// Possible behavior pref values +#define IMAGE_ACCEPT 0 +#define IMAGE_NOFOREIGN 1 +#define IMAGE_DENY 2 -//////////////////////////////////////////////////////////////////////////////// +static const char kImageBehaviorPrefName[] = "network.image.imageBehavior"; +static const char kImageWarningPrefName[] = "network.image.warnAboutImages"; +static const char kImageBlockerPrefName[] = "imageblocker.enabled"; +static const char kImageBlockImageInMailNewsPrefName[] = "mailnews.message_display.disable_remote_image"; +static const PRInt32 kImageBehaviorPrefDefault = IMAGE_ACCEPT; +static const PRBool kImageWarningPrefDefault = PR_FALSE; +static const PRBool kImageBlockerPrefDefault = PR_FALSE; +static const PRBool kImageBlockImageInMailNewsPrefDefault = PR_FALSE; //////////////////////////////////////////////////////////////////////////////// // nsImgManager Implementation +//////////////////////////////////////////////////////////////////////////////// -NS_IMPL_ISUPPORTS2(nsImgManager, +NS_IMPL_ISUPPORTS4(nsImgManager, nsIImgManager, - nsIContentPolicy); + nsIContentPolicy, + nsIObserver, + nsSupportsWeakReference); nsImgManager::nsImgManager() { } -nsImgManager::~nsImgManager(void) +nsImgManager::~nsImgManager() { } nsresult nsImgManager::Init() { - IMAGE_RegisterPrefCallbacks(); - nsresult rv; - mIOService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv); - return rv; + nsresult rv; + + // On error, just don't use the host based lookup anymore. We can do the + // other things, like mailnews blocking + mPermissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); + + mPrefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv); + + if (NS_SUCCEEDED(rv)) { + nsCOMPtr prefInternal = do_QueryInterface(mPrefBranch, &rv); + if (NS_SUCCEEDED(rv)) { + prefInternal->AddObserver(kImageBehaviorPrefName, this, PR_TRUE); + + // We don't do anything with it yet, but let it be. (bug 110112, 146513) + prefInternal->AddObserver(kImageWarningPrefName, this, PR_TRUE); + + // What is this pref, and how do you set it? + prefInternal->AddObserver(kImageBlockerPrefName, this, PR_TRUE); + prefInternal->AddObserver(kImageBlockImageInMailNewsPrefName, this, PR_TRUE); + } + } + + rv = ReadPrefs(); + NS_ASSERTION(NS_SUCCEEDED(rv), "Error occured reading image preferences"); + + return NS_OK; } - -NS_IMETHODIMP nsImgManager::Block(nsIURI* imageURI) -{ - ::IMAGE_Block(imageURI); - return NS_OK; -} - - // nsIContentPolicy Implementation NS_IMETHODIMP nsImgManager::ShouldLoad(PRInt32 aContentType, nsIURI *aContentLoc, nsISupports *aContext, nsIDOMWindow *aWindow, - PRBool *_retval) + PRBool *aShouldLoad) { - *_retval = PR_TRUE; - nsresult rv = NS_OK; + *aShouldLoad = PR_TRUE; + nsresult rv = NS_OK; - // we can't do anything w/ out these. - if (!aContentLoc || !aContext) return rv; + // we can't do anything w/ out these. + if (!aContentLoc || !aContext) return rv; - switch (aContentType) { - case nsIContentPolicy::IMAGE: - { - // First, let be sure we are processing an HTTP or HTTPS images. - // We should not waste time with chrome url... - PRBool httpType; - rv = aContentLoc->SchemeIs("http", &httpType); - if (NS_FAILED(rv) || !httpType) { - // check HTTPS as well - rv = aContentLoc->SchemeIs("https", &httpType); - if (NS_FAILED(rv) || !httpType) return rv; - } - - nsCOMPtr baseURI; - nsCOMPtr doc; - nsCOMPtr content(do_QueryInterface(aContext)); - NS_ASSERTION(content, "no content avail"); - if (content) { - rv = content->GetDocument(*getter_AddRefs(doc)); - if (NS_FAILED(rv) || !doc) return rv; - - rv = doc->GetBaseURL(*getter_AddRefs(baseURI)); - if (NS_FAILED(rv) || !baseURI) return rv; - - // Let check if we are running a mail window, doesn't matter if mail images are allowed - if (IMAGE_BlockedInMail()) { - nsCOMPtr docshell; - rv = GetRootDocShell(aWindow, getter_AddRefs(docshell)); - if (docshell) { - PRUint32 appType; - rv = docshell->GetAppType(&appType); - if (NS_SUCCEEDED(rv) && appType == nsIDocShell::APP_TYPE_MAIL) { - //we are dealing with an mail or newsgroup window, let's block the image - *_retval = PR_FALSE; - return NS_OK; - } - } - } - - nsCAutoString baseHost; - rv = baseURI->GetAsciiHost(baseHost); - if (NS_FAILED(rv)) return rv; - - nsCAutoString host; - rv = aContentLoc->GetAsciiHost(host); - if (NS_FAILED(rv)) return rv; - - return ::IMAGE_CheckForPermission(host.get(), baseHost.get(), - _retval); - } - } - break; + if (aContentType == nsIContentPolicy::IMAGE) { + // First, let be sure we are processing an HTTP or HTTPS images. + // We should not waste time with chrome url... + PRBool httpType; + rv = aContentLoc->SchemeIs("http", &httpType); + if (NS_FAILED(rv) || !httpType) { + // check HTTPS as well + rv = aContentLoc->SchemeIs("https", &httpType); + if (NS_FAILED(rv) || !httpType) return rv; } - return NS_OK; + + nsCOMPtr baseURI; + nsCOMPtr doc; + nsCOMPtr content = do_QueryInterface(aContext); + NS_ASSERTION(content, "no content available"); + if (content) { + rv = content->GetDocument(*getter_AddRefs(doc)); + if (NS_FAILED(rv) || !doc) return rv; + + rv = doc->GetBaseURL(*getter_AddRefs(baseURI)); + if (NS_FAILED(rv) || !baseURI) return rv; + + // Let check if we are running a mail window, doesn't matter if mail images are allowed + if (mBlockInMailNewsPref) { + nsCOMPtr docshell; + rv = GetRootDocShell(aWindow, getter_AddRefs(docshell)); + if (docshell) { + PRUint32 appType; + rv = docshell->GetAppType(&appType); + if (NS_SUCCEEDED(rv) && appType == nsIDocShell::APP_TYPE_MAIL) { + //we are dealing with an mail or newsgroup window, let's block the image + *aShouldLoad = PR_FALSE; + return NS_OK; + } + } + } + + rv = TestPermission(aContentLoc, baseURI, aShouldLoad); + if (NS_FAILED(rv)) return rv; + } + } + return NS_OK; } NS_IMETHODIMP nsImgManager::ShouldProcess(PRInt32 aContentType, nsIURI *aDocumentLoc, nsISupports *aContext, nsIDOMWindow *aWindow, - PRBool *_retval) { + PRBool *_retval) +{ return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMETHODIMP nsImgManager::GetRootDocShell(nsIDOMWindow *aWindow, nsIDocShell **result) +NS_IMETHODIMP +nsImgManager::TestPermission(nsIURI *aCurrentURI, + nsIURI *aFirstURI, + PRBool *aPermission) +{ + nsresult rv; + *aPermission = PR_TRUE; + + // return if imageblocker is not enabled + // TODO: Why? Where is the pref set? + if (!mBlockerPref) { + *aPermission = (mBehaviorPref != IMAGE_DENY); + return NS_OK; + } + + if (mBehaviorPref == IMAGE_DENY) { + *aPermission = PR_FALSE; + return NS_OK; + } + + // Third party checking + if (mBehaviorPref == IMAGE_NOFOREIGN) { + // compare tails of names checking to see if they have a common domain + // we do this by comparing the tails of both names where each tail + // includes at least one dot + + // A more generic method somewhere would be nice + + nsCAutoString currentHost; + rv = aCurrentURI->GetAsciiHost(currentHost); + if (NS_FAILED(rv)) return rv; + + // Search for two dots, starting at the end. + // If there are no two dots found, ++dot will turn to zero, + // that will return the entire string. + PRInt32 dot = currentHost.RFindChar('.'); + dot = currentHost.RFindChar('.', dot-1); + ++dot; + + // Get the domain, ie the last part of the host (www.domain.com -> domain.com) + // This will break on co.uk + const nsACString &tail = Substring(currentHost, dot, currentHost.Length() - dot); + + nsCAutoString firstHost; + rv = aFirstURI->GetAsciiHost(firstHost); + if (NS_FAILED(rv)) return rv; + + // Get the last part of the firstUri with the same length as |tail| + const nsACString &firstTail = Substring(firstHost, dot, firstHost.Length() - dot); + + // Check that both tails are the same, and that just before the tail in + // |firstUri| there is a dot. That means both url are in the same domain + if ((dot > 0 && firstHost.CharAt(dot-1) != '.') || !tail.Equals(firstTail)) { + *aPermission = PR_FALSE; + return NS_OK; + } + } + + if (mPermissionManager) { + PRUint32 temp; + mPermissionManager->TestPermission(aCurrentURI, nsIPermissionManager::IMAGE_TYPE, &temp); + // Blacklist for now + *aPermission = (temp != nsIPermissionManager::DENY_ACTION); + } else { + // no premission manager, return ok + *aPermission = PR_TRUE; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsImgManager::Observe(nsISupports *aSubject, + const char *aTopic, + const PRUnichar *aData) +{ + nsresult rv; + + // check the topic, and the cached prefservice + if (!mPrefBranch) { + NS_ERROR("No prefbranch"); + return NS_ERROR_FAILURE; + } + + if (!nsCRT::strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) { + // which pref changed? + NS_ConvertUCS2toUTF8 pref(aData); + + if (pref.Equals(kImageBehaviorPrefName)) { + rv = mPrefBranch->GetIntPref(kImageBehaviorPrefName, &mBehaviorPref); + if (NS_FAILED(rv) || mBehaviorPref < 0 || mBehaviorPref > 2) { + mBehaviorPref = kImageBehaviorPrefDefault; + } + } else if (pref.Equals(kImageWarningPrefName)) { + rv = mPrefBranch->GetIntPref(kImageWarningPrefName, &mWarningPref); + if (NS_FAILED(rv)) { + mWarningPref = kImageWarningPrefDefault; + } + } else if (pref.Equals(kImageBlockerPrefName)) { + rv = mPrefBranch->GetIntPref(kImageBlockerPrefName, &mBlockerPref); + if (NS_FAILED(rv)) { + mBlockerPref = kImageBlockerPrefDefault; + } + } else if (pref.Equals(kImageBlockImageInMailNewsPrefName)) { + rv = mPrefBranch->GetIntPref(kImageBlockImageInMailNewsPrefName, &mBlockInMailNewsPref); + if (NS_FAILED(rv)) { + mBlockInMailNewsPref = kImageBlockImageInMailNewsPrefDefault; + } + } + } + + return NS_OK; +} + +nsresult +nsImgManager::ReadPrefs() +{ + nsresult rv, rv2 = NS_OK; + + // check the prefservice is cached + if (!mPrefBranch) { + NS_ERROR("No prefbranch"); + return NS_ERROR_FAILURE; + } + + rv = mPrefBranch->GetIntPref(kImageBehaviorPrefName, &mBehaviorPref); + if (NS_FAILED(rv) || mBehaviorPref < 0 || mBehaviorPref > 2) { + rv2 = rv; + mBehaviorPref = kImageBehaviorPrefDefault; + } + + rv = mPrefBranch->GetBoolPref(kImageBlockerPrefName, &mBlockerPref); + if (NS_FAILED(rv)) { + rv2 = rv; + mBlockerPref = kImageWarningPrefDefault; + } + + rv = mPrefBranch->GetBoolPref(kImageWarningPrefName, &mWarningPref); + if (NS_FAILED(rv)) { + rv2 = rv; + mWarningPref = kImageBlockerPrefDefault; + } + + rv = mPrefBranch->GetBoolPref(kImageBlockImageInMailNewsPrefName, &mBlockInMailNewsPref); + if (NS_FAILED(rv)) { + rv2 = rv; + mBlockInMailNewsPref = kImageBlockImageInMailNewsPrefDefault; + } + + return rv2; +} + +NS_IMETHODIMP +nsImgManager::GetRootDocShell(nsIDOMWindow *aWindow, nsIDocShell **result) { nsresult rv; diff --git a/extensions/cookie/nsImgManager.h b/extensions/cookie/nsImgManager.h index 501d2d6d2554..f4ee210be911 100644 --- a/extensions/cookie/nsImgManager.h +++ b/extensions/cookie/nsImgManager.h @@ -44,11 +44,19 @@ #include "nsCOMPtr.h" #include "nsIIOService.h" #include "nsIDocShell.h" +#include "nsIObserver.h" +#include "nsWeakReference.h" +#include "nsIPermissionManager.h" + +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" //////////////////////////////////////////////////////////////////////////////// class nsImgManager : public nsIImgManager, - public nsIContentPolicy + public nsIContentPolicy, + public nsIObserver, + public nsSupportsWeakReference { public: @@ -56,17 +64,32 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSIIMGMANAGER NS_DECL_NSICONTENTPOLICY + NS_DECL_NSIOBSERVER nsImgManager(); - virtual ~nsImgManager(void); + virtual ~nsImgManager(); nsresult Init(); +private: + + nsresult ReadPrefs(); + + PRBool mBlockerPref; + PRInt32 mBehaviorPref; + PRBool mWarningPref; + PRBool mBlockInMailNewsPref; + + PRBool mPolicy; + protected: NS_IMETHOD GetRootDocShell(nsIDOMWindow *aWindow, nsIDocShell **result); - // cached IOService - nsCOMPtr mIOService; - + nsCOMPtr mPermissionManager; + nsCOMPtr mPrefBranch; }; +// {D60B3710-166D-11d5-A542-0010A401EB10} +#define NS_IMGMANAGER_CID \ +{ 0xd60b3710, 0x166d, 0x11d5, { 0xa5, 0x42, 0x0, 0x10, 0xa4, 0x1, 0xeb, 0x10 } } + #endif /* nsImgManager_h__ */ diff --git a/extensions/cookie/nsModuleFactory.cpp b/extensions/cookie/nsModuleFactory.cpp index 4d277638dcc3..b43b95b18f8f 100644 --- a/extensions/cookie/nsModuleFactory.cpp +++ b/extensions/cookie/nsModuleFactory.cpp @@ -53,6 +53,7 @@ #include "nsICategoryManager.h" #include "nsXPIDLString.h" #include "nsCookiePromptService.h" +#include "nsCookiePermission.h" // Define the constructor function for the objects NS_GENERIC_FACTORY_CONSTRUCTOR(nsCookie) @@ -64,6 +65,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPermissionManager, Init) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPopupWindowManager, Init) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsCookieHTTPNotify, Init) NS_GENERIC_FACTORY_CONSTRUCTOR(nsCookiePromptService) +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsCookiePermission, Init) static NS_METHOD RegisterContentPolicy(nsIComponentManager *aCompMgr, nsIFile *aPath, @@ -140,6 +142,11 @@ static const nsModuleComponentInfo components[] = { NS_COOKIEPROMPTSERVICE_CONTRACTID, nsCookiePromptServiceConstructor }, + { "CookiePermission", + NS_COOKIEPERMISSION_CID, + NS_COOKIEPERMISSION_CONTRACTID, + nsCookiePermissionConstructor + }, { NS_COOKIEHTTPNOTIFY_CLASSNAME, NS_COOKIEHTTPNOTIFY_CID, NS_COOKIEHTTPNOTIFY_CONTRACTID, diff --git a/extensions/cookie/nsPermission.cpp b/extensions/cookie/nsPermission.cpp index 3ac84d56b8f9..64af9ec1ba7b 100644 --- a/extensions/cookie/nsPermission.cpp +++ b/extensions/cookie/nsPermission.cpp @@ -45,38 +45,33 @@ NS_IMPL_ISUPPORTS2(nsPermission, nsIPermission, nsISupportsWeakReference); nsPermission::nsPermission() - : permissionHost(0) { } nsPermission::nsPermission - (char * host, - PRInt32 type, - PRBool capability) { - permissionHost = host; - permissionType = type; - permissionCapability = capability; + (const nsACString &aHost, + PRUint32 aType, + PRUint32 aCapability) +: mHost(aHost), + mType(aType), + mCapability(aCapability) +{ } -nsPermission::~nsPermission(void) { - if (permissionHost) - PL_strfree(permissionHost); +nsPermission::~nsPermission() { } -NS_IMETHODIMP nsPermission::GetHost(char * *aHost) { - if (permissionHost) { - *aHost = (char *) nsMemory::Clone(permissionHost, strlen(permissionHost) + 1); - return NS_OK; - } - return NS_ERROR_NULL_POINTER; -} - -NS_IMETHODIMP nsPermission::GetType(PRInt32 *aType) { - *aType = permissionType; +NS_IMETHODIMP nsPermission::GetHost(nsACString& aHost) { + aHost = mHost; return NS_OK; } -NS_IMETHODIMP nsPermission::GetCapability(PRBool *aCapability) { - *aCapability = permissionCapability; +NS_IMETHODIMP nsPermission::GetType(PRUint32 *aType) { + *aType = mType; + return NS_OK; +} + +NS_IMETHODIMP nsPermission::GetCapability(PRUint32 *aCapability) { + *aCapability = mCapability; return NS_OK; } diff --git a/extensions/cookie/nsPermission.h b/extensions/cookie/nsPermission.h index 655f2a64e3fa..a2dcd579059e 100644 --- a/extensions/cookie/nsPermission.h +++ b/extensions/cookie/nsPermission.h @@ -41,27 +41,30 @@ #include "nsIPermission.h" #include "nsWeakReference.h" +#include "nsString.h" //////////////////////////////////////////////////////////////////////////////// class nsPermission : public nsIPermission, - public nsSupportsWeakReference { + public nsSupportsWeakReference +{ public: - // nsISupports NS_DECL_ISUPPORTS NS_DECL_NSIPERMISSION - // Note: following constructor takes ownership of the host string so the caller - // of the constructor must not free them - nsPermission(char * host, PRInt32 type, PRBool capability); + nsPermission(const nsACString &aHost, PRUint32 aType, PRUint32 aCapability); nsPermission(); - virtual ~nsPermission(void); + virtual ~nsPermission(); protected: - char * permissionHost; - PRInt32 permissionType; - PRBool permissionCapability; + nsCString mHost; + PRUint32 mType; + PRUint32 mCapability; }; +// {28F16D80-157B-11d5-A542-0010A401EB10} +#define NS_PERMISSION_CID \ +{ 0x28f16d80, 0x157b, 0x11d5, { 0xa5, 0x42, 0x0, 0x10, 0xa4, 0x1, 0xeb, 0x10 } } + #endif /* nsPermission_h__ */ diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp index 346c303ad698..e1b77682b317 100644 --- a/extensions/cookie/nsPermissionManager.cpp +++ b/extensions/cookie/nsPermissionManager.cpp @@ -38,70 +38,99 @@ #include "nsIServiceManager.h" #include "nsPermissionManager.h" +#include "nsPermission.h" #include "nsCRT.h" -#include "nsPermissions.h" #include "nsIGenericFactory.h" #include "nsXPIDLString.h" #include "nsIScriptGlobalObject.h" #include "nsIDOMWindowInternal.h" #include "nsIPrompt.h" -#include "nsIObserverService.h" -#include "nsPermission.h" #include "nsNetUtil.h" +#include "nsILineInputStream.h" +#include "nsIPrefBranch.h" +#include "nsIPrefBranchInternal.h" +#include "nsIPrefService.h" +#include "nsAppDirectoryServiceDefs.h" +#include "prprf.h" -static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); +static NS_NAMED_LITERAL_CSTRING(kPermissionsFileName, "cookperm.txt"); +static const char kPermissionChangeNotification[] = PERM_CHANGE_NOTIFICATION; + +typedef struct { + nsCString host; + nsVoidArray permissionList; +} permission_HostStruct; + +typedef struct { + PRUint32 type; + PRUint32 permission; +} permission_TypeStruct; //////////////////////////////////////////////////////////////////////////////// class nsPermissionEnumerator : public nsISimpleEnumerator { - public: + public: + NS_DECL_ISUPPORTS + + nsPermissionEnumerator(const nsVoidArray &aPermissionList) + : mHostCount(aPermissionList.Count()), + mHostIndex(0), + mTypeIndex(0), + mPermissionList(aPermissionList) + { + } + + NS_IMETHOD GetNext(nsISupports **result); - NS_DECL_ISUPPORTS + NS_IMETHOD HasMoreElements(PRBool *aResult) + { + *aResult = mHostCount > mHostIndex; + return NS_OK; + } - nsPermissionEnumerator() : mHostCount(0), mTypeCount(0) - { - } + virtual ~nsPermissionEnumerator() + { + } - NS_IMETHOD HasMoreElements(PRBool *result) - { - *result = PERMISSION_HostCount() > mHostCount; - return NS_OK; - } - - NS_IMETHOD GetNext(nsISupports **result) - { - char *host; - PRBool capability; - PRInt32 type; - nsresult rv = PERMISSION_Enumerate - (mHostCount, mTypeCount++, &host, &type, &capability); - if (NS_SUCCEEDED(rv)) { - if (mTypeCount == PERMISSION_TypeCount(mHostCount)) { - mTypeCount = 0; - mHostCount++; - } - nsIPermission *permission = - new nsPermission(host, type, capability); - *result = permission; - NS_ADDREF(*result); - } else { - *result = nsnull; - } - return rv; - } - - virtual ~nsPermissionEnumerator() - { - } - - protected: - PRInt32 mHostCount; - PRInt32 mTypeCount; + protected: + PRInt32 mHostCount; + PRInt32 mHostIndex; + PRInt32 mTypeIndex; + const nsVoidArray &mPermissionList; }; NS_IMPL_ISUPPORTS1(nsPermissionEnumerator, nsISimpleEnumerator); +NS_IMETHODIMP +nsPermissionEnumerator::GetNext(nsISupports **aResult) +{ + if (mHostIndex >= mHostCount) { + *aResult = nsnull; + return NS_ERROR_FAILURE; + } + + permission_HostStruct *hostStruct = NS_STATIC_CAST(permission_HostStruct*, mPermissionList.ElementAt(mHostIndex)); + NS_ASSERTION(hostStruct, "corrupt permission list"); + + permission_TypeStruct *typeStruct = NS_STATIC_CAST(permission_TypeStruct*, hostStruct->permissionList.ElementAt(mTypeIndex++)); + if (mTypeIndex == hostStruct->permissionList.Count()) { + mTypeIndex = 0; + mHostIndex++; + } + + nsIPermission *permission = + new nsPermission(hostStruct->host, typeStruct->type, typeStruct->permission); + if (!permission) { + *aResult = nsnull; + return NS_ERROR_OUT_OF_MEMORY; + } + *aResult = permission; + NS_ADDREF(permission); + return NS_OK; +} + + //////////////////////////////////////////////////////////////////////////////// // nsPermissionManager Implementation @@ -111,65 +140,239 @@ nsPermissionManager::nsPermissionManager() { } -nsPermissionManager::~nsPermissionManager(void) +nsPermissionManager::~nsPermissionManager() { - PERMISSION_RemoveAll(); + RemoveAllFromMemory(); } nsresult nsPermissionManager::Init() { - PERMISSION_Read(); - nsresult rv; - nsCOMPtr observerService = - do_GetService("@mozilla.org/observer-service;1", &rv); - if (observerService) { - observerService->AddObserver(this, "profile-before-change", PR_FALSE); - observerService->AddObserver(this, "profile-do-change", PR_FALSE); + + // Cache the permissions file + rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mPermissionsFile)); + if (NS_SUCCEEDED(rv)) { + rv = mPermissionsFile->AppendNative(kPermissionsFileName); } - mIOService = do_GetIOService(); - return rv; -} + // Ignore an error. That is not a problem. No cookperm.txt usually. + Read(); + + mObserverService = do_GetService("@mozilla.org/observer-service;1", &rv); + if (NS_SUCCEEDED(rv)) { + mObserverService->AddObserver(this, "profile-before-change", PR_TRUE); + mObserverService->AddObserver(this, "profile-do-change", PR_TRUE); + } -NS_IMETHODIMP nsPermissionManager::Add - (const nsACString & objectURI, PRBool permission, PRInt32 type) { - // XXX ideally we should change this interface to pass nsIURI - nsCOMPtr uri; - NS_NewURI(getter_AddRefs(uri), objectURI, nsnull, nsnull, mIOService); - ::PERMISSION_Add(uri, permission, type); return NS_OK; } -NS_IMETHODIMP nsPermissionManager::TestForBlocking - (const nsACString &objectURI, PRInt32 type, PRBool* blocked) { - // XXX ideally we should change this interface to pass nsIURI - nsCOMPtr uri; - NS_NewURI(getter_AddRefs(uri), objectURI, nsnull, nsnull, mIOService); - ::PERMISSION_TestForBlocking(uri, blocked, type); - return NS_OK; -} - -NS_IMETHODIMP nsPermissionManager::RemoveAll(void) { - ::PERMISSION_RemoveAll(); - ::PERMISSION_DeletePersistentUserData(); - return NS_OK; -} - -NS_IMETHODIMP nsPermissionManager::GetEnumerator(nsISimpleEnumerator * *entries) +NS_IMETHODIMP +nsPermissionManager::Add(nsIURI *aURI, + PRUint32 aType, + PRUint32 aPermission) { - *entries = nsnull; + NS_ASSERTION(aURI, "could not get uri"); + nsresult rv; - nsPermissionEnumerator* permissionEnum = new nsPermissionEnumerator(); - if (permissionEnum == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(permissionEnum); - *entries = permissionEnum; + nsCAutoString hostPort; + aURI->GetHostPort(hostPort); + if (hostPort.IsEmpty()) { + // Nothing to add return NS_OK; + } + + rv = AddInternal(hostPort, aType, aPermission); + if (NS_FAILED(rv)) return rv; + + // Notify permission manager dialog to update its display + // + // This used to be conditional, but now we use AddInternal + // for cases when no notification is needed + NotifyObservers(hostPort); + + mChangedList = PR_TRUE; + return Write(); } -NS_IMETHODIMP nsPermissionManager::Remove(const nsACString & host, PRInt32 type) { - ::PERMISSION_Remove(host, type); +//Only add to memory, don't save. That's up to the caller. +nsresult +nsPermissionManager::AddInternal(const nsACString &aHost, + PRUint32 aType, + PRUint32 aPermission) +{ + // find existing entry for host + permission_HostStruct *hostStruct; + PRBool hostFound = PR_FALSE; + PRInt32 hostCount = mPermissionList.Count(); + PRInt32 hostIndex; + for (hostIndex = 0; hostIndex < hostCount; ++hostIndex) { + hostStruct = NS_STATIC_CAST(permission_HostStruct*, mPermissionList.ElementAt(hostIndex)); + NS_ASSERTION(hostStruct, "corrupt permission list"); + if (aHost.Equals(hostStruct->host)) { + // host found in list + hostFound = PR_TRUE; + break; + } else if (aHost < hostStruct->host) { + // Need to insert new entry here for alphabetized list + break; + } + } + + if (!hostFound) { + // create a host structure for the host + hostStruct = new permission_HostStruct; + if (!hostStruct) { + return NS_ERROR_OUT_OF_MEMORY; + } + + hostStruct->host = aHost; + + // Insert host structure into the list + if (hostIndex < hostCount) { + mPermissionList.InsertElementAt(hostStruct, hostIndex); + } else { + mPermissionList.AppendElement(hostStruct); + } + } + + // See if host already has an entry for this type + permission_TypeStruct *typeStruct; + PRInt32 typeCount = hostStruct->permissionList.Count(); + for (PRInt32 typeIndex=0; typeIndex < typeCount; ++typeIndex) { + typeStruct = NS_STATIC_CAST(permission_TypeStruct*, hostStruct->permissionList.ElementAt(typeIndex)); + NS_ASSERTION(typeStruct, "corrupt permission list"); + if (typeStruct->type == aType) { + // Type found. Modify the corresponding permission + typeStruct->permission = aPermission; + return NS_OK; + } + } + + // Create a type structure and attach it to the host structure + typeStruct = new permission_TypeStruct; + typeStruct->type = aType; + typeStruct->permission = aPermission; + hostStruct->permissionList.AppendElement(typeStruct); + + return NS_OK; +} + +NS_IMETHODIMP +nsPermissionManager::Remove(const nsACString &aHost, + PRUint32 aType) +{ + nsresult rv; + + // Find existing entry for host + permission_HostStruct *hostStruct; + + PRInt32 hostCount = mPermissionList.Count(); + for (PRInt32 hostIndex = 0; hostIndex < hostCount; ++hostIndex) { + hostStruct = NS_STATIC_CAST(permission_HostStruct*, mPermissionList.ElementAt(hostIndex)); + NS_ASSERTION(hostStruct, "corrupt permission list"); + + if (aHost.Equals(hostStruct->host)) { + // Host found in list, see if it has an entry for this type + permission_TypeStruct *typeStruct; + + PRInt32 typeCount = hostStruct->permissionList.Count(); + for (PRInt32 typeIndex = 0; typeIndex < typeCount; ++typeIndex) { + typeStruct = NS_STATIC_CAST(permission_TypeStruct*, hostStruct->permissionList.ElementAt(typeIndex)); + NS_ASSERTION(typeStruct, "corrupt permission list"); + if (typeStruct->type == aType) { + delete typeStruct; + hostStruct->permissionList.RemoveElementAt(typeIndex); + --typeCount; + + // If no more types are present, remove the entry + if (typeCount == 0) { + mPermissionList.RemoveElementAt(hostIndex); + delete hostStruct; + } + mChangedList = PR_TRUE; + Write(); + + // Notify Observers + NotifyObservers(aHost); + + return NS_OK; + } + } + + break; + } + } + return NS_OK; +} + +NS_IMETHODIMP +nsPermissionManager::RemoveAll() +{ + RemoveAllFromMemory(); + Write(); + return NS_OK; +} + +NS_IMETHODIMP +nsPermissionManager::TestPermission(nsIURI *aURI, + PRUint32 aType, + PRUint32 *aPermission) +{ + NS_ASSERTION(aURI, "could not get uri"); + NS_ASSERTION(aPermission, "no permission pointer"); + + // set the default + *aPermission = nsIPermissionManager::UNKNOWN_ACTION; + + nsCAutoString hostPort; + aURI->GetHostPort(hostPort); + // Don't error on no host. Just return UNKNOWN_ACTION as permission. + if (hostPort.IsEmpty()) { + return NS_OK; + } + + permission_HostStruct *hostStruct; + permission_TypeStruct *typeStruct; + + //TODO: Look for the specific host, if not found check its domains + // Do we want that? Currenty, it is not actually done + + // find host name within list + PRInt32 hostCount = mPermissionList.Count(); + for (PRInt32 i = 0; i < hostCount; ++i) { + hostStruct = NS_STATIC_CAST(permission_HostStruct*, mPermissionList.ElementAt(i)); + NS_ASSERTION(hostStruct, "corrupt permission list"); + + if (hostStruct->host.Equals(hostPort)) { + // search for type in the permission list for this host + PRInt32 typeCount = hostStruct->permissionList.Count(); + for (PRInt32 typeIndex = 0; typeIndex < typeCount; ++typeIndex) { + typeStruct = NS_STATIC_CAST(permission_TypeStruct*, hostStruct->permissionList.ElementAt(typeIndex)); + NS_ASSERTION(typeStruct, "corrupt permission list"); + + if (typeStruct->type == aType) { + // type found. Obtain the corresponding permission + *aPermission = typeStruct->permission; + return NS_OK; + } + } + } + } + + return NS_OK; +} + +NS_IMETHODIMP nsPermissionManager::GetEnumerator(nsISimpleEnumerator **aEnum) +{ + + nsPermissionEnumerator* permissionEnum = new nsPermissionEnumerator(mPermissionList); + if (!permissionEnum) { + *aEnum = nsnull; + return NS_ERROR_OUT_OF_MEMORY; + } + NS_ADDREF(permissionEnum); + *aEnum = permissionEnum; return NS_OK; } @@ -188,15 +391,228 @@ NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aT // was accepted). If this condition ever changes, the permission // file would need to be updated here. - PERMISSION_RemoveAll(); + RemoveAllFromMemory(); if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) - PERMISSION_DeletePersistentUserData(); + if (mPermissionsFile) { + mPermissionsFile->Remove(PR_FALSE); + } } else if (!nsCRT::strcmp(aTopic, "profile-do-change")) { // The profile has aleady changed. // Now just read them from the new profile location. - PERMISSION_Read(); + + // Re-get the permissions file + rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mPermissionsFile)); + if (NS_SUCCEEDED(rv)) { + rv = mPermissionsFile->AppendNative(kPermissionsFileName); + } + Read(); } return rv; } + +//***************************************************************************** +//*** nsPermissionManager private methods +//***************************************************************************** + +nsresult +nsPermissionManager::RemoveAllFromMemory() +{ + permission_HostStruct *hostStruct; + permission_TypeStruct *typeStruct; + + PRInt32 hostCount = mPermissionList.Count(); + for (PRInt32 hostIndex = hostCount-1; hostIndex >= 0; --hostIndex) { + hostStruct = NS_STATIC_CAST(permission_HostStruct*, mPermissionList.ElementAt(hostIndex)); + NS_ASSERTION(hostStruct, "corrupt permission list"); + + PRInt32 typeCount = hostStruct->permissionList.Count(); + for (PRInt32 typeIndex = typeCount-1; typeIndex >= 0; --typeIndex) { + typeStruct = NS_STATIC_CAST(permission_TypeStruct*, hostStruct->permissionList.ElementAt(typeIndex)); + delete typeStruct; + hostStruct->permissionList.RemoveElementAt(typeIndex); + } + // no more types are present, remove the entry + mPermissionList.RemoveElementAt(hostIndex); + delete hostStruct; + } + + return NS_OK; +} + +// broadcast a notification that a permission pref has changed +nsresult +nsPermissionManager::NotifyObservers(const nsACString &aHost) +{ + if (mObserverService) { + return mObserverService->NotifyObservers(NS_STATIC_CAST(nsIPermissionManager *, this), + kPermissionChangeNotification, + NS_ConvertUTF8toUCS2(aHost).get()); + } + return NS_ERROR_FAILURE; +} + +// Note: +// We don't do checkbox states here anymore. +// When a consumer wants it back, that is up to the consumer, not this backend +// For cookies, it is now done with a persist in the dialog xul file. + +nsresult +nsPermissionManager::Read() +{ + nsresult rv; + + if (!mPermissionsFile) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr fileInputStream; + rv = NS_NewLocalFileInputStream(getter_AddRefs(fileInputStream), mPermissionsFile); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr lineInputStream = do_QueryInterface(fileInputStream, &rv); + if (NS_FAILED(rv)) return rv; + + /* format is: + * host \t number permission \t number permission ... \n + * if this format isn't respected we move onto the next line in the file. + */ + + nsAutoString bufferUnicode; + nsCAutoString buffer; + PRBool isMore = PR_TRUE; + while (isMore && NS_SUCCEEDED(lineInputStream->ReadLine(bufferUnicode, &isMore))) { + CopyUCS2toASCII(bufferUnicode, buffer); + if (buffer.IsEmpty() || buffer.First() == '#') { + continue; + } + + PRInt32 hostIndex, permissionIndex; + PRUint32 nextPermissionIndex = 0; + hostIndex = 0; + + if ((permissionIndex = buffer.FindChar('\t', hostIndex) + 1) == 0) { + continue; + } + + // ignore leading periods in host name + while (hostIndex < permissionIndex && (buffer.CharAt(hostIndex) == '.')) { + ++hostIndex; + } + + nsDependentCSubstring host(buffer, hostIndex, permissionIndex - hostIndex - 1); + + for (;;) { + if (nextPermissionIndex == buffer.Length()+1) { + break; + } + if ((nextPermissionIndex = buffer.FindChar('\t', permissionIndex)+1) == 0) { + nextPermissionIndex = buffer.Length()+1; + } + const nsASingleFragmentCString &permissionString = Substring(buffer, permissionIndex, nextPermissionIndex - permissionIndex - 1); + permissionIndex = nextPermissionIndex; + + PRUint32 type = 0; + PRUint32 index = 0; + + if (permissionString.IsEmpty()) { + continue; // empty permission entry -- should never happen + } + // Parse "2T" + char c = permissionString.CharAt(index); + while (index < permissionString.Length() && c >= '0' && c <= '9') { + type = 10*type + (c-'0'); + c = permissionString.CharAt(++index); + } + if (index >= permissionString.Length()) { + continue; // bad format for this permission entry + } + PRUint32 permission = (permissionString.CharAt(index) == 'T') ? nsIPermissionManager::ALLOW_ACTION : nsIPermissionManager::DENY_ACTION; + + // Ignore @@@ as host. Old style checkbox status + if (!permissionString.IsEmpty() && !host.Equals(NS_LITERAL_CSTRING("@@@@"))) { + rv = AddInternal(host, type, permission); + if (NS_FAILED(rv)) return rv; + } + + } + } + + mChangedList = PR_FALSE; + + return NS_OK; +} + +nsresult +nsPermissionManager::Write() +{ + nsresult rv; + + if (!mChangedList) { + return NS_OK; + } + + if (!mPermissionsFile) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr fileOutputStream; + rv = NS_NewLocalFileOutputStream(getter_AddRefs(fileOutputStream), mPermissionsFile); + if (NS_FAILED(rv)) return rv; + + // get a buffered output stream 4096 bytes big, to optimize writes + nsCOMPtr bufferedOutputStream; + rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream), fileOutputStream, 4096); + if (NS_FAILED(rv)) return rv; + + permission_HostStruct *hostStruct; + permission_TypeStruct *typeStruct; + + static const char kHeader[] = + "# HTTP Permission File\n" + "# http://www.netscape.com/newsref/std/cookie_spec.html\n" + "# This is a generated file! Do not edit.\n\n"; + + bufferedOutputStream->Write(kHeader, sizeof(kHeader) - 1, &rv); + + /* format shall be: + * host \t permission \t permission ... \n + */ + static const char kTab[] = "\t"; + static const char kNew[] = "\n"; + static const char kTrue[] = "F"; + static const char kFalse[] = "T"; + + PRInt32 hostCount = mPermissionList.Count(); + for (PRInt32 i = 0; i < hostCount; ++i) { + hostStruct = NS_STATIC_CAST(permission_HostStruct*, mPermissionList.ElementAt(i)); + NS_ASSERTION(hostStruct, "corrupt permission list"); + + bufferedOutputStream->Write(hostStruct->host.get(), hostStruct->host.Length(), &rv); + + PRUint32 typeCount = hostStruct->permissionList.Count(); + for (PRUint32 typeIndex = 0; typeIndex < typeCount; ++typeIndex) { + typeStruct = NS_STATIC_CAST(permission_TypeStruct*, hostStruct->permissionList.ElementAt(typeIndex)); + NS_ASSERTION(typeStruct, "corrupt permission list"); + + bufferedOutputStream->Write(kTab, sizeof(kTab) - 1, &rv); + + char typeString[5]; + PRUint32 len = PR_snprintf(typeString, sizeof(typeString), "%u", typeStruct->type); + bufferedOutputStream->Write(typeString, len, &rv); + + if (typeStruct->permission == nsIPermissionManager::ALLOW_ACTION) { + bufferedOutputStream->Write(kTrue, sizeof(kTrue) - 1, &rv); + } else if (typeStruct->permission == nsIPermissionManager::DENY_ACTION) { + bufferedOutputStream->Write(kFalse, sizeof(kFalse) - 1, &rv); + } + } + bufferedOutputStream->Write(kNew, sizeof(kNew) - 1, &rv); + } + + mChangedList = PR_FALSE; + + return NS_OK; +} + diff --git a/extensions/cookie/nsPermissionManager.h b/extensions/cookie/nsPermissionManager.h index ba5a0d73fd73..222dfb1658ee 100644 --- a/extensions/cookie/nsPermissionManager.h +++ b/extensions/cookie/nsPermissionManager.h @@ -41,15 +41,19 @@ #include "nsIPermissionManager.h" #include "nsIObserver.h" +#include "nsIObserverService.h" #include "nsWeakReference.h" #include "nsCOMPtr.h" #include "nsIIOService.h" +#include "nsVoidArray.h" +#include "nsIFile.h" //////////////////////////////////////////////////////////////////////////////// class nsPermissionManager : public nsIPermissionManager, public nsIObserver, - public nsSupportsWeakReference { + public nsSupportsWeakReference +{ public: // nsISupports @@ -58,13 +62,29 @@ public: NS_DECL_NSIOBSERVER nsPermissionManager(); - virtual ~nsPermissionManager(void); + virtual ~nsPermissionManager(); nsresult Init(); -protected: - // cached IOService - nsCOMPtr mIOService; - +private: + + nsresult AddInternal(const nsACString &aHost, + PRUint32 aType, + PRUint32 aPermission); + + nsresult Read(); + nsresult Write(); + nsresult NotifyObservers(const nsACString &aHost); + nsresult RemoveAllFromMemory(); + + nsCOMPtr mObserverService; + nsCOMPtr mPermissionsFile; + nsVoidArray mPermissionList; + PRBool mChangedList; + }; +// {4F6B5E00-0C36-11d5-A535-0010A401EB10} +#define NS_PERMISSIONMANAGER_CID \ +{ 0x4f6b5e00, 0xc36, 0x11d5, { 0xa5, 0x35, 0x0, 0x10, 0xa4, 0x1, 0xeb, 0x10 } } + #endif /* nsPermissionManager_h__ */ diff --git a/extensions/cookie/nsPopupWindowManager.cpp b/extensions/cookie/nsPopupWindowManager.cpp index 4ee4066cda51..3c1fe028f998 100644 --- a/extensions/cookie/nsPopupWindowManager.cpp +++ b/extensions/cookie/nsPopupWindowManager.cpp @@ -39,8 +39,8 @@ #include "nsCOMPtr.h" #include "nsCRT.h" -#include "nsPermissions.h" #include "nsPermission.h" +#include "nsIPermissionManager.h" #include "nsIObserverService.h" #include "nsIPrefBranch.h" @@ -49,69 +49,11 @@ #include "nsIServiceManagerUtils.h" #include "nsIURI.h" -/* - The Popup Window Manager maintains popup window permissions by website. +/** + * The Popup Window Manager maintains popup window permissions by website. */ -#define POPUP_PREF "dom.disable_open_during_load" -static const char sPopupDisablePref[] = POPUP_PREF; -static const char sPermissionChangeNotification[] = PPM_CHANGE_NOTIFICATION; -static const char sXPCOMShutdownTopic[] = NS_XPCOM_SHUTDOWN_OBSERVER_ID; -static const char sPrefChangedTopic[] = NS_PREFBRANCH_PREFCHANGE_TOPIC_ID; - -class nsPopupEnumerator : public nsISimpleEnumerator -{ - public: - - NS_DECL_ISUPPORTS - - nsPopupEnumerator() : mHostCurrent(0), mTypeCurrent(0), mHostsFound(0) - { - mHostCount = PERMISSION_HostCountForType(WINDOWPERMISSION); - } - - NS_IMETHOD HasMoreElements(PRBool *result) - { - *result = mHostCount > mHostsFound; - return NS_OK; - } - - NS_IMETHOD GetNext(nsISupports **result) - { - char *host; - PRBool capability; - PRInt32 type; - - *result = nsnull; - - while (NS_SUCCEEDED(PERMISSION_Enumerate(mHostCurrent, mTypeCurrent++, &host, &type, &capability))) { - if ((mTypeCurrent == PERMISSION_TypeCount(mHostCurrent)) || (type == WINDOWPERMISSION)) { - mTypeCurrent = 0; - mHostCurrent++; - } - if (type == WINDOWPERMISSION) { - nsIPermission *permission = new nsPermission(host, type, capability); - *result = permission; - NS_ADDREF(*result); - mHostsFound++; - break; - } - } - return NS_OK; - } - - virtual ~nsPopupEnumerator() - { - } - - protected: - PRInt32 mHostCurrent; - PRInt32 mTypeCurrent; - PRInt32 mHostCount; - PRInt32 mHostsFound; -}; - -NS_IMPL_ISUPPORTS1(nsPopupEnumerator, nsISimpleEnumerator); +static const char kPopupDisablePref[] = "dom.disable_open_during_load"; //***************************************************************************** //*** nsPopupWindowManager object management and nsISupports @@ -124,31 +66,35 @@ nsPopupWindowManager::nsPopupWindowManager() : nsPopupWindowManager::~nsPopupWindowManager(void) { - StopObservingThings(); } -NS_IMPL_ISUPPORTS2(nsPopupWindowManager, +NS_IMPL_ISUPPORTS3(nsPopupWindowManager, nsIPopupWindowManager, - nsIObserver); + nsIObserver, + nsSupportsWeakReference); nsresult nsPopupWindowManager::Init() { - mOS = do_GetService("@mozilla.org/observer-service;1"); - // we bypass the permission manager API's but it still owns the underlying - // list--we need to let it do the initializing to avoid conflict. - mPermManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); - nsCOMPtr prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); - if (prefs) - prefs->GetBranch("", getter_AddRefs(mPopupPrefBranch)); + nsresult rv; + mPermissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); - if (mOS && mPermManager && mPopupPrefBranch) { - // initialize our local copy of the pref - Observe(NS_STATIC_CAST(nsIPopupWindowManager *, this), - sPrefChangedTopic, NS_LITERAL_STRING(POPUP_PREF).get()); - return ObserveThings(); - } - return NS_ERROR_FAILURE; + mPrefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv)) { + PRBool permission; + rv = mPrefBranch->GetBoolPref(kPopupDisablePref, &permission); + if (NS_FAILED(rv)) { + permission = PR_FALSE; + } + mPolicy = permission ? DENY_POPUP : ALLOW_POPUP; + + nsCOMPtr prefInternal = do_QueryInterface(mPrefBranch, &rv); + if (NS_SUCCEEDED(rv)) { + prefInternal->AddObserver(kPopupDisablePref, this, PR_TRUE); + } + } + + return NS_OK; } //***************************************************************************** @@ -166,210 +112,56 @@ nsPopupWindowManager::GetDefaultPermission(PRUint32 *aDefaultPermission) NS_IMETHODIMP nsPopupWindowManager::SetDefaultPermission(PRUint32 aDefaultPermission) { - mPolicy = (aDefaultPermission == DENY_POPUP) ? DENY_POPUP : ALLOW_POPUP; + mPolicy = aDefaultPermission; return NS_OK; } + NS_IMETHODIMP -nsPopupWindowManager::Add(nsIURI *aURI, PRBool aPermit) +nsPopupWindowManager::TestPermission(nsIURI *aURI, PRUint32 *aPermission) { NS_ENSURE_ARG_POINTER(aURI); - if (!mPermManager) - // if we couldn't initialize the permission manager Permission_AddHost() - // will create a new list that could stomp an existing cookperm.txt - return NS_ERROR_FAILURE; - - nsCAutoString uri; - aURI->GetHostPort(uri); - if (uri.IsEmpty()) - return NS_ERROR_FAILURE; - - if (NS_SUCCEEDED(Permission_AddHost(uri, aPermit, WINDOWPERMISSION, PR_TRUE))) - return NotifyObservers(aURI); - - return NS_ERROR_FAILURE; -} + NS_ENSURE_ARG_POINTER(aPermission); -NS_IMETHODIMP -nsPopupWindowManager::Remove(nsIURI *aURI) -{ - NS_ENSURE_ARG_POINTER(aURI); - - nsCAutoString uri; - aURI->GetHostPort(uri); - if (uri.IsEmpty()) - return NS_ERROR_FAILURE; - - PERMISSION_Remove(uri, WINDOWPERMISSION); - return NotifyObservers(aURI); -} - -NS_IMETHODIMP -nsPopupWindowManager::RemoveAll() -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -/* The underlying manager, nsPermissionManager, won't store permissions - for an url lacking a host. It's good to know these things up front. -*/ -NS_IMETHODIMP -nsPopupWindowManager::TestSuitability(nsIURI *aURI, PRBool *_retval) -{ - NS_ENSURE_ARG_POINTER(aURI); - NS_ENSURE_ARG_POINTER(_retval); - - nsCAutoString hostPort; - aURI->GetHostPort(hostPort); - *_retval = hostPort.IsEmpty() ? PR_FALSE : PR_TRUE; - return NS_OK; -} - -NS_IMETHODIMP -nsPopupWindowManager::TestPermission(nsIURI *aURI, PRUint32 *_retval) -{ - NS_ENSURE_ARG_POINTER(aURI); - NS_ENSURE_ARG_POINTER(_retval); - - *_retval = mPolicy; - - nsCAutoString uri; - aURI->GetHostPort(uri); - if (uri.IsEmpty()) - return NS_OK; - - /* Look for the specific host, if not found check its domains */ nsresult rv; - PRBool permission; - PRInt32 offset = 0; - const char* host = uri.get(); - do { - rv = permission_CheckFromList(host+offset, permission, WINDOWPERMISSION); - if (NS_SUCCEEDED(rv)) { - /* found a value for the host/domain */ - *_retval = permission ? ALLOW_POPUP : DENY_POPUP; - break; + PRUint32 permit; + + if (mPermissionManager) { + rv = mPermissionManager->TestPermission(aURI, + nsIPermissionManager::POPUP_TYPE, + &permit); + + // Share some constants between interfaces? + if (permit == nsIPermissionManager::ALLOW_ACTION) { + *aPermission = ALLOW_POPUP; + } else if (permit == nsIPermissionManager::DENY_ACTION) { + *aPermission = DENY_POPUP; + } else { + *aPermission = mPolicy; } - - /* try the parent domain */ - offset = uri.FindChar('.', offset) + 1; - } while (offset > 0 ); - + } else { + *aPermission = mPolicy; + } return NS_OK; } -NS_IMETHODIMP -nsPopupWindowManager::GetEnumerator(nsISimpleEnumerator **_retval) -{ - *_retval = nsnull; - - nsPopupEnumerator* popupEnum = new nsPopupEnumerator(); - if (popupEnum == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - - NS_ADDREF(popupEnum); - *_retval = popupEnum; - return NS_OK; -} - -NS_IMETHODIMP -nsPopupWindowManager::AddObserver(nsIObserver *aObserver) -{ - if (mOS) - return mOS->AddObserver(aObserver, sPermissionChangeNotification, PR_FALSE); - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -nsPopupWindowManager::RemoveObserver(nsIObserver *aObserver) -{ - if (mOS) - return mOS->RemoveObserver(aObserver, sPermissionChangeNotification); - return NS_ERROR_FAILURE; -} - //***************************************************************************** //*** nsPopupWindowManager::nsIObserver //***************************************************************************** NS_IMETHODIMP -nsPopupWindowManager::Observe(nsISupports *aSubject, const char *aTopic, +nsPopupWindowManager::Observe(nsISupports *aSubject, + const char *aTopic, const PRUnichar *aData) { - if (nsCRT::strcmp(aTopic, sPrefChangedTopic) == 0 && - NS_LITERAL_STRING(POPUP_PREF).Equals(aData)) { + NS_ConvertUCS2toUTF8 pref(aData); + if (pref.Equals(kPopupDisablePref)) { // refresh our local copy of the "disable popups" pref PRBool permission = PR_FALSE; - if (mPopupPrefBranch) { - mPopupPrefBranch->GetBoolPref(sPopupDisablePref, &permission); + if (mPrefBranch) { + mPrefBranch->GetBoolPref(kPopupDisablePref, &permission); } mPolicy = permission ? DENY_POPUP : ALLOW_POPUP; - } else if (nsCRT::strcmp(aTopic, sXPCOMShutdownTopic) == 0) { - // unhook cyclical references - StopObservingThings(); - DeInitialize(); } return NS_OK; } - -//***************************************************************************** -//*** nsPopupWindowManager private methods -//***************************************************************************** - -/* Register for notifications of interest. That's a change in the pref - we're watching and XPCOM shutdown. */ -nsresult -nsPopupWindowManager::ObserveThings() -{ - nsresult rv = NS_ERROR_FAILURE; - - if (mOS) - rv = mOS->AddObserver(this, sXPCOMShutdownTopic, PR_FALSE); - - if (NS_SUCCEEDED(rv)) { - nsCOMPtr ibranch(do_QueryInterface(mPopupPrefBranch)); - if (ibranch) { - ibranch->AddObserver(sPopupDisablePref, this, PR_FALSE); - } - } - - return rv; -} - -// undo ObserveThings -nsresult -nsPopupWindowManager::StopObservingThings() -{ - nsCOMPtr ibranch(do_QueryInterface(mPopupPrefBranch)); - if (ibranch) { - ibranch->RemoveObserver(sPopupDisablePref, this); - } - - if (mOS) - mOS->RemoveObserver(this, sXPCOMShutdownTopic); - - return NS_OK; -} - -// broadcast a notification that a popup pref has changed -nsresult -nsPopupWindowManager::NotifyObservers(nsIURI *aURI) -{ - if (mOS) { - nsCAutoString uri; - aURI->GetSpec(uri); - return mOS->NotifyObservers(NS_STATIC_CAST(nsIPopupWindowManager *, this), - sPermissionChangeNotification, NS_ConvertUTF8toUCS2(uri).get()); - } - return NS_ERROR_FAILURE; -} - -// unhook cyclical references so we can be properly shut down -void -nsPopupWindowManager::DeInitialize() -{ - mOS = 0; - mPermManager = 0; - mPopupPrefBranch = 0; -} - diff --git a/extensions/cookie/nsPopupWindowManager.h b/extensions/cookie/nsPopupWindowManager.h index 9c05444abc24..2098ea2cb158 100644 --- a/extensions/cookie/nsPopupWindowManager.h +++ b/extensions/cookie/nsPopupWindowManager.h @@ -45,11 +45,13 @@ #include "nsIPermissionManager.h" #include "nsIPopupWindowManager.h" #include "nsIPrefBranch.h" +#include "nsWeakReference.h" class nsIURI; class nsPopupWindowManager : public nsIPopupWindowManager, - public nsIObserver { + public nsIObserver, + public nsSupportsWeakReference { public: NS_DECL_ISUPPORTS @@ -61,15 +63,9 @@ public: nsresult Init(); private: - nsresult ObserveThings(); - nsresult StopObservingThings(); - nsresult NotifyObservers(nsIURI *aURI); - void DeInitialize(); - PRUint32 mPolicy; - nsCOMPtr mOS; - nsCOMPtr mPermManager; - nsCOMPtr mPopupPrefBranch; + nsCOMPtr mPermissionManager; + nsCOMPtr mPrefBranch; }; // {4275d3f4-752a-427a-b432-14d5dda1c20b} diff --git a/extensions/cookie/resources/content/cookieAcceptDialog.js b/extensions/cookie/resources/content/cookieAcceptDialog.js index 8963a694cf19..565b296d654e 100644 --- a/extensions/cookie/resources/content/cookieAcceptDialog.js +++ b/extensions/cookie/resources/content/cookieAcceptDialog.js @@ -126,7 +126,8 @@ function onload() messageParent.appendChild(descriptionNode); } - document.getElementById('persistDomainAcceptance').checked = params.GetInt(nsICookieAcceptDialog.REMEMBER_DECISION) > 0; + // Must we remember the decision? + params.SetInt(nsICookieAcceptDialog.REMEMBER_DECISION, document.getElementById('persistDomainAcceptance').checked); if (cookie) { document.getElementById('ifl_name').setAttribute("value",cookie.name); @@ -166,7 +167,7 @@ function showhideinfo() sizeToContent(); } -function onChangePersitence() +function onChangePersistence() { params.SetInt(nsICookieAcceptDialog.REMEMBER_DECISION, document.getElementById('persistDomainAcceptance').checked); } diff --git a/extensions/cookie/resources/content/cookieAcceptDialog.xul b/extensions/cookie/resources/content/cookieAcceptDialog.xul index 8e472f4ea4ba..3f62dcbdb04d 100644 --- a/extensions/cookie/resources/content/cookieAcceptDialog.xul +++ b/extensions/cookie/resources/content/cookieAcceptDialog.xul @@ -70,8 +70,9 @@ - + diff --git a/extensions/cookie/resources/content/cookieNavigatorOverlay.xul b/extensions/cookie/resources/content/cookieNavigatorOverlay.xul index 9b0a2f5e9dee..6b04076820ff 100644 --- a/extensions/cookie/resources/content/cookieNavigatorOverlay.xul +++ b/extensions/cookie/resources/content/cookieNavigatorOverlay.xul @@ -34,6 +34,7 @@ // both are necessary. popupmanager is just a special case // of permissionmanager but does extra work on add/remove + const nsIPermissionManager = Components.interfaces.nsIPermissionManager; var permissionmanager; var popupmanager; @@ -54,6 +55,7 @@ // determine which items we need to hide or disable from the task menu function CheckForVisibility() { + var uri = getBrowser().currentURI; // obtain access to permissionmanager and popupmanager // (popup manager is a wrapper around permission that does extra work) @@ -69,17 +71,17 @@ } // determine current state (blocked or unblocked) and hide appropriate menu item - var blocked; + var blocked = nsIPermissionManager.UNKNOWN_ACTION; blocked = - permissionmanager.testForBlocking(window._content.location, COOKIEPERMISSION); - enableElement("AllowCookies", blocked); - enableElement("BlockCookies", !blocked); + permissionmanager.testPermission(uri, nsIPermissionManager.COOKIE_TYPE); + enableElement("AllowCookies", blocked != nsIPermissionManager.ALLOW_ACTION); + enableElement("BlockCookies", blocked != nsIPermissionManager.DENY_ACTION); blocked = - permissionmanager.testForBlocking(window._content.location, IMAGEPERMISSION); - enableElement("AllowImages", blocked); - enableElement("BlockImages", !blocked); + permissionmanager.testPermission(uri, nsIPermissionManager.IMAGE_TYPE); + enableElement("AllowImages", blocked != nsIPermissionManager.ALLOW_ACTION); + enableElement("BlockImages", blocked != nsIPermissionManager.DENY_ACTION); SetPopupMenuEnabledState(); @@ -104,30 +106,13 @@ } function SetPopupMenuEnabledState() { - var suitable = false; - var blocked = false; + var blocked = nsIPermissionManager.UNKNOWN_ACTION; var policy = pref.getBoolPref("dom.disable_open_during_load"); - suitable = popupmanager.testSuitability(getBrowser().currentURI); - if (suitable) { - if (!policy) // blacklist, test if there is a permission set - blocked = (popupmanager.testPermission(getBrowser().currentURI) == Components.interfaces.nsIPopupWindowManager.DENY_POPUP); - else { // whitelist, check if it is on list - blocked = true; - var enumerator = popupmanager.getEnumerator(); - while (enumerator.hasMoreElements()) { - var permission = enumerator.getNext() - .QueryInterface(Components.interfaces.nsIPermission); - if (permission.capability && getBrowser().currentURI.host == permission.host) { - blocked = false; - break; - } - } - } - } + blocked = permissionmanager.testPermission(getBrowser().currentURI, nsIPermissionManager.POPUP_TYPE); - enableElement("BlockPopups", suitable && !blocked); - enableElement("AllowPopups", suitable && blocked); + enableElement("BlockPopups", blocked != nsIPermissionManager.DENY_ACTION); + enableElement("AllowPopups", blocked != nsIPermissionManager.ALLOW_ACTION); enableElement("ManagePopups", true); } @@ -147,24 +132,25 @@ return; } var element; + var uri = getBrowser().currentURI; switch (action) { case "cookieAllow": - permissionmanager.add(window._content.location, true, COOKIEPERMISSION); + permissionmanager.add(uri, nsIPermissionManager.COOKIE_TYPE, nsIPermissionManager.ALLOW_ACTION); element = document.getElementById("AllowCookies"); alert(element.getAttribute("msg")); break; case "cookieBlock": - permissionmanager.add(window._content.location, false, COOKIEPERMISSION); + permissionmanager.add(uri, nsIPermissionManager.COOKIE_TYPE, nsIPermissionManager.DENY_ACTION); element = document.getElementById("BlockCookies"); alert(element.getAttribute("msg")); break; case "imageAllow": - permissionmanager.add(window._content.location, true, IMAGEPERMISSION); + permissionmanager.add(uri, nsIPermissionManager.IMAGE_TYPE, nsIPermissionManager.ALLOW_ACTION); element = document.getElementById("AllowImages"); alert(element.getAttribute("msg")); break; case "imageBlock": - permissionmanager.add(window._content.location, false, IMAGEPERMISSION); + permissionmanager.add(uri, nsIPermissionManager.IMAGE_TYPE, nsIPermissionManager.DENY_ACTION); element = document.getElementById("BlockImages"); alert(element.getAttribute("msg")); break; @@ -178,18 +164,12 @@ switch (action) { case "block": - if (!policy) - popupmanager.add(uri, policy); - else - popupmanager.remove(uri); + permissionmanager.add(uri, nsIPermissionManager.POPUP_TYPE, nsIPermissionManager.DENY_ACTION); break; case "allow": var browsers = getBrowser().browsers; var popupIcon = document.getElementById("popupIcon"); - if (!policy) - popupmanager.remove(uri); - else - popupmanager.add(uri, policy); + permissionmanager.add(uri, nsIPermissionManager.POPUP_TYPE, nsIPermissionManager.ALLOW_ACTION); for (var i = 0; i < browsers.length; i++) { if (browsers[i].popupDomain == uri.host) { browsers[i].popupDomain = null; diff --git a/toolkit/components/cookie/content/cookieAcceptDialog.js b/toolkit/components/cookie/content/cookieAcceptDialog.js index 8963a694cf19..565b296d654e 100644 --- a/toolkit/components/cookie/content/cookieAcceptDialog.js +++ b/toolkit/components/cookie/content/cookieAcceptDialog.js @@ -126,7 +126,8 @@ function onload() messageParent.appendChild(descriptionNode); } - document.getElementById('persistDomainAcceptance').checked = params.GetInt(nsICookieAcceptDialog.REMEMBER_DECISION) > 0; + // Must we remember the decision? + params.SetInt(nsICookieAcceptDialog.REMEMBER_DECISION, document.getElementById('persistDomainAcceptance').checked); if (cookie) { document.getElementById('ifl_name').setAttribute("value",cookie.name); @@ -166,7 +167,7 @@ function showhideinfo() sizeToContent(); } -function onChangePersitence() +function onChangePersistence() { params.SetInt(nsICookieAcceptDialog.REMEMBER_DECISION, document.getElementById('persistDomainAcceptance').checked); } diff --git a/toolkit/components/cookie/content/cookieAcceptDialog.xul b/toolkit/components/cookie/content/cookieAcceptDialog.xul index 8e472f4ea4ba..3f62dcbdb04d 100644 --- a/toolkit/components/cookie/content/cookieAcceptDialog.xul +++ b/toolkit/components/cookie/content/cookieAcceptDialog.xul @@ -70,8 +70,9 @@ - + diff --git a/xpfe/appshell/public/nsIPopupWindowManager.idl b/xpfe/appshell/public/nsIPopupWindowManager.idl index 4a7d3bb61c52..f11f1c9177c2 100644 --- a/xpfe/appshell/public/nsIPopupWindowManager.idl +++ b/xpfe/appshell/public/nsIPopupWindowManager.idl @@ -62,61 +62,12 @@ interface nsIPopupWindowManager : nsISupports { */ attribute PRUint32 defaultPermission; - /** - * Add permission information for a website. - * @param aURI the website to be blocked - * @param aPermit true to grant permission to the website - * false to refuse permission - */ - void add(in nsIURI aURI, in boolean aPermit); - - /** - * Remove permission information for a website. Popups will be permitted - * or not depending on whether this is a white- or black-list. - * is permitted to show popups.) - * @param aURI the website to be unblocked - */ - void remove(in nsIURI aURI); - - /** - * Clear permission information for all websites. - */ - void removeAll(); - - /** - * Test whether a website is suitable for popup permission storage. - * @param aURI the website to be tested - * @return true if permission can be stored for the website - */ - boolean testSuitability(in nsIURI aURI); - /** * Test whether a website has permission to show a popup window. - * @param aURI the website to be tested - * @return one of the ALLOW/DENY consts defined above + * @param uri is the URI to be tested + * @return one of the enumerated permission actions defined above */ - PRUint32 testPermission(in nsIURI aURI); - - /** - * Enumerates all stored permissions - * @return an enumerator which itself returns nsISupports objects which - * can be QIed to an nsIPermission - */ - nsISimpleEnumerator getEnumerator(); - - /** - * This service broadcasts a PPM_CHANGE_NOTIFICATION notification - * when any popup permission changes. Add yourself as an observer. - * @param observer the observer - */ - void addObserver(in nsIObserver aObserver); - - /** - * This service broadcasts a PPM_CHANGE_NOTIFICATION notification - * when any popup permission changes. Remove yourself as an observer. - * @param observer the observer - */ - void removeObserver(in nsIObserver aObserver); + PRUint32 testPermission(in nsIURI uri); }; %{ C++ diff --git a/xpfe/communicator/resources/content/nsContextMenu.js b/xpfe/communicator/resources/content/nsContextMenu.js index 734c83cb7694..a581f0f2f134 100644 --- a/xpfe/communicator/resources/content/nsContextMenu.js +++ b/xpfe/communicator/resources/content/nsContextMenu.js @@ -462,8 +462,6 @@ nsContextMenu.prototype = { // but cancel if it's an unsuitable URL const PM = Components.classes["@mozilla.org/PopupWindowManager;1"] .getService(CI.nsIPopupWindowManager); - if (!PM.testSuitability(this.popupURL)) - this.popupURL = null; } } catch(e) { } diff --git a/xpfe/communicator/resources/content/popupManager.js b/xpfe/communicator/resources/content/popupManager.js index 49b71d6dc6fc..57edfeab404c 100644 --- a/xpfe/communicator/resources/content/popupManager.js +++ b/xpfe/communicator/resources/content/popupManager.js @@ -21,7 +21,11 @@ * * ***** END LICENSE BLOCK ***** */ +const nsIPermissionManager = Components.interfaces.nsIPermissionManager; +const popupType = nsIPermissionManager.POPUP_TYPE; + var popupManager = null; +var permissionManager = null; var permissions = []; @@ -31,8 +35,6 @@ var listCapability; // the capability of sites on the currently viewed list // FALSE: current popup policy is ALLOW ALL WITH EXCEPTIONS - sites on // the blacklist are blocked and have permission.capability = false -const POPUP_TYPE = 2; - var additions = []; var removals = []; @@ -66,6 +68,8 @@ var popupStringBundle; function Startup() { popupManager = Components.classes["@mozilla.org/PopupWindowManager;1"] .getService(Components.interfaces.nsIPopupWindowManager); + permissionManager = Components.classes["@mozilla.org/permissionmanager;1"] + .getService(Components.interfaces.nsIPermissionManager); permissionsTree = document.getElementById("permissionsTree"); @@ -204,15 +208,18 @@ function Permission(host, number) { } function loadPermissions(table) { - var enumerator = popupManager.getEnumerator(); + var enumerator = permissionManager.enumerator; var count = 0; while (enumerator.hasMoreElements()) { - var permission = enumerator.getNext() - .QueryInterface(Components.interfaces.nsIPermission); - if (permission.capability == listCapability) { - var host = permission.host; - table[count] = new Permission(host,count++); + var permission = enumerator.getNext(); + if (permission) { + permission = permission.QueryInterface(Components.interfaces.nsIPermission); + if ((permission.type == popupType) && + (permission.capability == listCapability)) { + var host = permission.host; + table[count] = new Permission(host,count++); + } } } } @@ -297,7 +304,7 @@ function deleteAllPermissions() { } function updatePendingRemovals(host) { - if (additions[host] != null) + if (additions[host]) additions[host] = null; else removals[host] = host; @@ -317,23 +324,26 @@ function finalizeChanges() { var ioService = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService); + var uri; + var host; + var i; + + var perm = (listCapability == true) ? nsIPermissionManager.ALLOW_ACTION : nsIPermissionManager.DENY_ACTION //note: the scheme will be taken off later, it is being added now only to //create the uri for add/remove - for (var i in additions) { - var host = additions[i]; + for (i in additions) { + host = additions[i]; if (host != null) { host = "http://" + host; - var uri = ioService.newURI(host, null, null); - popupManager.add(uri, listCapability); + uri = ioService.newURI(host, null, null); + permissionManager.add(uri, popupType, listCapability); } } - for (var i in removals) { - var host = removals[i]; + for (i in removals) { + host = removals[i]; if (host != null) { - host = "http://" + host; - var uri = ioService.newURI(host, null, null); - popupManager.remove(uri); + permissionManager.remove(host, popupType); } } diff --git a/xpfe/components/permissions/content/permissionsManager.js b/xpfe/components/permissions/content/permissionsManager.js index 49b71d6dc6fc..57edfeab404c 100644 --- a/xpfe/components/permissions/content/permissionsManager.js +++ b/xpfe/components/permissions/content/permissionsManager.js @@ -21,7 +21,11 @@ * * ***** END LICENSE BLOCK ***** */ +const nsIPermissionManager = Components.interfaces.nsIPermissionManager; +const popupType = nsIPermissionManager.POPUP_TYPE; + var popupManager = null; +var permissionManager = null; var permissions = []; @@ -31,8 +35,6 @@ var listCapability; // the capability of sites on the currently viewed list // FALSE: current popup policy is ALLOW ALL WITH EXCEPTIONS - sites on // the blacklist are blocked and have permission.capability = false -const POPUP_TYPE = 2; - var additions = []; var removals = []; @@ -66,6 +68,8 @@ var popupStringBundle; function Startup() { popupManager = Components.classes["@mozilla.org/PopupWindowManager;1"] .getService(Components.interfaces.nsIPopupWindowManager); + permissionManager = Components.classes["@mozilla.org/permissionmanager;1"] + .getService(Components.interfaces.nsIPermissionManager); permissionsTree = document.getElementById("permissionsTree"); @@ -204,15 +208,18 @@ function Permission(host, number) { } function loadPermissions(table) { - var enumerator = popupManager.getEnumerator(); + var enumerator = permissionManager.enumerator; var count = 0; while (enumerator.hasMoreElements()) { - var permission = enumerator.getNext() - .QueryInterface(Components.interfaces.nsIPermission); - if (permission.capability == listCapability) { - var host = permission.host; - table[count] = new Permission(host,count++); + var permission = enumerator.getNext(); + if (permission) { + permission = permission.QueryInterface(Components.interfaces.nsIPermission); + if ((permission.type == popupType) && + (permission.capability == listCapability)) { + var host = permission.host; + table[count] = new Permission(host,count++); + } } } } @@ -297,7 +304,7 @@ function deleteAllPermissions() { } function updatePendingRemovals(host) { - if (additions[host] != null) + if (additions[host]) additions[host] = null; else removals[host] = host; @@ -317,23 +324,26 @@ function finalizeChanges() { var ioService = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService); + var uri; + var host; + var i; + + var perm = (listCapability == true) ? nsIPermissionManager.ALLOW_ACTION : nsIPermissionManager.DENY_ACTION //note: the scheme will be taken off later, it is being added now only to //create the uri for add/remove - for (var i in additions) { - var host = additions[i]; + for (i in additions) { + host = additions[i]; if (host != null) { host = "http://" + host; - var uri = ioService.newURI(host, null, null); - popupManager.add(uri, listCapability); + uri = ioService.newURI(host, null, null); + permissionManager.add(uri, popupType, listCapability); } } - for (var i in removals) { - var host = removals[i]; + for (i in removals) { + host = removals[i]; if (host != null) { - host = "http://" + host; - var uri = ioService.newURI(host, null, null); - popupManager.remove(uri); + permissionManager.remove(host, popupType); } } diff --git a/xpfe/components/permissions/content/permissionsNavigatorOverlay.xul b/xpfe/components/permissions/content/permissionsNavigatorOverlay.xul index 9b0a2f5e9dee..6b04076820ff 100644 --- a/xpfe/components/permissions/content/permissionsNavigatorOverlay.xul +++ b/xpfe/components/permissions/content/permissionsNavigatorOverlay.xul @@ -34,6 +34,7 @@ // both are necessary. popupmanager is just a special case // of permissionmanager but does extra work on add/remove + const nsIPermissionManager = Components.interfaces.nsIPermissionManager; var permissionmanager; var popupmanager; @@ -54,6 +55,7 @@ // determine which items we need to hide or disable from the task menu function CheckForVisibility() { + var uri = getBrowser().currentURI; // obtain access to permissionmanager and popupmanager // (popup manager is a wrapper around permission that does extra work) @@ -69,17 +71,17 @@ } // determine current state (blocked or unblocked) and hide appropriate menu item - var blocked; + var blocked = nsIPermissionManager.UNKNOWN_ACTION; blocked = - permissionmanager.testForBlocking(window._content.location, COOKIEPERMISSION); - enableElement("AllowCookies", blocked); - enableElement("BlockCookies", !blocked); + permissionmanager.testPermission(uri, nsIPermissionManager.COOKIE_TYPE); + enableElement("AllowCookies", blocked != nsIPermissionManager.ALLOW_ACTION); + enableElement("BlockCookies", blocked != nsIPermissionManager.DENY_ACTION); blocked = - permissionmanager.testForBlocking(window._content.location, IMAGEPERMISSION); - enableElement("AllowImages", blocked); - enableElement("BlockImages", !blocked); + permissionmanager.testPermission(uri, nsIPermissionManager.IMAGE_TYPE); + enableElement("AllowImages", blocked != nsIPermissionManager.ALLOW_ACTION); + enableElement("BlockImages", blocked != nsIPermissionManager.DENY_ACTION); SetPopupMenuEnabledState(); @@ -104,30 +106,13 @@ } function SetPopupMenuEnabledState() { - var suitable = false; - var blocked = false; + var blocked = nsIPermissionManager.UNKNOWN_ACTION; var policy = pref.getBoolPref("dom.disable_open_during_load"); - suitable = popupmanager.testSuitability(getBrowser().currentURI); - if (suitable) { - if (!policy) // blacklist, test if there is a permission set - blocked = (popupmanager.testPermission(getBrowser().currentURI) == Components.interfaces.nsIPopupWindowManager.DENY_POPUP); - else { // whitelist, check if it is on list - blocked = true; - var enumerator = popupmanager.getEnumerator(); - while (enumerator.hasMoreElements()) { - var permission = enumerator.getNext() - .QueryInterface(Components.interfaces.nsIPermission); - if (permission.capability && getBrowser().currentURI.host == permission.host) { - blocked = false; - break; - } - } - } - } + blocked = permissionmanager.testPermission(getBrowser().currentURI, nsIPermissionManager.POPUP_TYPE); - enableElement("BlockPopups", suitable && !blocked); - enableElement("AllowPopups", suitable && blocked); + enableElement("BlockPopups", blocked != nsIPermissionManager.DENY_ACTION); + enableElement("AllowPopups", blocked != nsIPermissionManager.ALLOW_ACTION); enableElement("ManagePopups", true); } @@ -147,24 +132,25 @@ return; } var element; + var uri = getBrowser().currentURI; switch (action) { case "cookieAllow": - permissionmanager.add(window._content.location, true, COOKIEPERMISSION); + permissionmanager.add(uri, nsIPermissionManager.COOKIE_TYPE, nsIPermissionManager.ALLOW_ACTION); element = document.getElementById("AllowCookies"); alert(element.getAttribute("msg")); break; case "cookieBlock": - permissionmanager.add(window._content.location, false, COOKIEPERMISSION); + permissionmanager.add(uri, nsIPermissionManager.COOKIE_TYPE, nsIPermissionManager.DENY_ACTION); element = document.getElementById("BlockCookies"); alert(element.getAttribute("msg")); break; case "imageAllow": - permissionmanager.add(window._content.location, true, IMAGEPERMISSION); + permissionmanager.add(uri, nsIPermissionManager.IMAGE_TYPE, nsIPermissionManager.ALLOW_ACTION); element = document.getElementById("AllowImages"); alert(element.getAttribute("msg")); break; case "imageBlock": - permissionmanager.add(window._content.location, false, IMAGEPERMISSION); + permissionmanager.add(uri, nsIPermissionManager.IMAGE_TYPE, nsIPermissionManager.DENY_ACTION); element = document.getElementById("BlockImages"); alert(element.getAttribute("msg")); break; @@ -178,18 +164,12 @@ switch (action) { case "block": - if (!policy) - popupmanager.add(uri, policy); - else - popupmanager.remove(uri); + permissionmanager.add(uri, nsIPermissionManager.POPUP_TYPE, nsIPermissionManager.DENY_ACTION); break; case "allow": var browsers = getBrowser().browsers; var popupIcon = document.getElementById("popupIcon"); - if (!policy) - popupmanager.remove(uri); - else - popupmanager.add(uri, policy); + permissionmanager.add(uri, nsIPermissionManager.POPUP_TYPE, nsIPermissionManager.ALLOW_ACTION); for (var i = 0; i < browsers.length; i++) { if (browsers[i].popupDomain == uri.host) { browsers[i].popupDomain = null;