Bug 1245184 - CookieManager should remove cookies only if they match the userContextId, r=sicking
--- a/browser/base/content/sanitize.js
+++ b/browser/base/content/sanitize.js
@@ -236,17 +236,18 @@ Sanitizer.prototype = {
if (range) {
// Iterate through the cookies and delete any created after our cutoff.
let cookiesEnum = cookieMgr.enumerator;
while (cookiesEnum.hasMoreElements()) {
let cookie = cookiesEnum.getNext().QueryInterface(Ci.nsICookie2);
if (cookie.creationTime > range[0]) {
// This cookie was created after our cutoff, clear it
- cookieMgr.remove(cookie.host, cookie.name, cookie.path, false);
+ cookieMgr.remove(cookie.host, cookie.name, cookie.path,
+ cookie.originAttributes, false);
if (++yieldCounter % YIELD_PERIOD == 0) {
yield new Promise(resolve => setTimeout(resolve, 0)); // Don't block the main thread too long
}
}
}
}
else {
--- a/browser/components/preferences/cookies.js
+++ b/browser/components/preferences/cookies.js
@@ -66,17 +66,19 @@ var gCookiesWindow = {
this._updateRemoveAllButton();
this._saveState();
},
_cookieEquals: function (aCookieA, aCookieB, aStrippedHost) {
return aCookieA.rawHost == aStrippedHost &&
aCookieA.name == aCookieB.name &&
- aCookieA.path == aCookieB.path;
+ aCookieA.path == aCookieB.path &&
+ ChromeUtils.isOriginAttributesEqual(aCookieA.originAttributes,
+ aCookieB.originAttributes);
},
observe: function (aCookie, aTopic, aData) {
if (aTopic != "cookie-changed")
return;
if (aCookie instanceof Components.interfaces.nsICookie) {
var strippedHost = this._makeStrippedHost(aCookie.host);
@@ -271,25 +273,29 @@ var gCookiesWindow = {
}
this._filterSet.splice(aIndex, removeCount);
return;
}
var item = this._getItemAtIndex(aIndex);
if (!item) return;
this._invalidateCache(aIndex - 1);
- if (item.container)
+ if (item.container) {
gCookiesWindow._hosts[item.rawHost] = null;
- else {
+ } else {
var parent = this._getItemAtIndex(item.parentIndex);
for (var i = 0; i < parent.cookies.length; ++i) {
var cookie = parent.cookies[i];
if (item.rawHost == cookie.rawHost &&
- item.name == cookie.name && item.path == cookie.path)
+ item.name == cookie.name &&
+ item.path == cookie.path &&
+ ChromeUtils.isOriginAttributesEqual(item.originAttributes,
+ cookie.originAttributes)) {
parent.cookies.splice(i, removeCount);
+ }
}
}
},
_invalidateCache: function (aIndex) {
this._cacheValid = Math.min(this._cacheValid, aIndex);
},
@@ -579,17 +585,18 @@ var gCookiesWindow = {
performDeletion: function gCookiesWindow_performDeletion(deleteItems) {
var psvc = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
var blockFutureCookies = false;
if (psvc.prefHasUserValue("network.cookie.blockFutureCookies"))
blockFutureCookies = psvc.getBoolPref("network.cookie.blockFutureCookies");
for (var i = 0; i < deleteItems.length; ++i) {
var item = deleteItems[i];
- this._cm.remove(item.host, item.name, item.path, blockFutureCookies);
+ this._cm.remove(item.host, item.name, item.path,
+ item.originAttributes, blockFutureCookies);
}
},
deleteCookie: function () {
// Selection Notes
// - Selection always moves to *NEXT* adjacent item unless item
// is last child at a given level in which case it moves to *PREVIOUS*
// item
--- a/dom/base/ChromeUtils.cpp
+++ b/dom/base/ChromeUtils.cpp
@@ -95,11 +95,22 @@ ChromeUtils::CreateOriginAttributesFromO
/* static */ void
ChromeUtils::CreateOriginAttributesFromDict(dom::GlobalObject& aGlobal,
const dom::OriginAttributesDictionary& aAttrs,
dom::OriginAttributesDictionary& aNewAttrs)
{
aNewAttrs = aAttrs;
}
+/* static */ bool
+ChromeUtils::IsOriginAttributesEqual(dom::GlobalObject& aGlobal,
+ const dom::OriginAttributesDictionary& aA,
+ const dom::OriginAttributesDictionary& aB)
+{
+ return aA.mAddonId == aB.mAddonId &&
+ aA.mAppId == aB.mAppId &&
+ aA.mInBrowser == aB.mInBrowser &&
+ aA.mSignedPkg == aB.mSignedPkg &&
+ aA.mUserContextId == aB.mUserContextId;
+}
} // namespace dom
} // namespace mozilla
--- a/dom/base/ChromeUtils.h
+++ b/dom/base/ChromeUtils.h
@@ -67,14 +67,19 @@ public:
const nsAString& aOrigin,
dom::OriginAttributesDictionary& aAttrs,
ErrorResult& aRv);
static void
CreateOriginAttributesFromDict(dom::GlobalObject& aGlobal,
const dom::OriginAttributesDictionary& aAttrs,
dom::OriginAttributesDictionary& aNewAttrs);
+
+ static bool
+ IsOriginAttributesEqual(dom::GlobalObject& aGlobal,
+ const dom::OriginAttributesDictionary& aA,
+ const dom::OriginAttributesDictionary& aB);
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ChromeUtils__
--- a/dom/webidl/ChromeUtils.webidl
+++ b/dom/webidl/ChromeUtils.webidl
@@ -58,16 +58,23 @@ interface ChromeUtils : ThreadSafeChrome
*
* @param originAttrs The origin attributes to copy.
* @returns An OriginAttributesDictionary copy of |originAttrs|
* with unspecified attributes added and assigned
* default values.
*/
static OriginAttributesDictionary
createOriginAttributesFromDict(optional OriginAttributesDictionary originAttrs);
+
+ /**
+ * Returns true if the 2 OriginAttributes are equal.
+ */
+ static boolean
+ isOriginAttributesEqual(optional OriginAttributesDictionary aA,
+ optional OriginAttributesDictionary aB);
};
/**
* Used by principals and the script security manager to represent origin
* attributes. The first dictionary is designed to contain the full set of
* OriginAttributes, the second is used for pattern-matching (i.e. does this
* OriginAttributesDictionary match the non-empty attributes in this pattern).
*
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -2361,19 +2361,25 @@ nsCookieService::Remove(const nsACString
return NS_OK;
}
NS_IMETHODIMP
nsCookieService::Remove(const nsACString &aHost,
const nsACString &aName,
const nsACString &aPath,
- bool aBlocked)
+ JS::HandleValue aOriginAttributes,
+ bool aBlocked,
+ JSContext* aCx)
{
NeckoOriginAttributes attrs;
+ if (!attrs.Init(aCx, aOriginAttributes)) {
+ return NS_ERROR_FAILURE;
+ }
+
return Remove(aHost, attrs, aName, aPath, aBlocked);
}
/******************************************************************************
* nsCookieService impl:
* private file I/O functions
******************************************************************************/
--- a/netwerk/cookie/nsICookieManager.idl
+++ b/netwerk/cookie/nsICookieManager.idl
@@ -34,16 +34,19 @@ interface nsICookieManager : nsISupports
* directly from the desired nsICookie object.
*
* @param aHost The host or domain for which the cookie was set. @see
* nsICookieManager2::add for a description of acceptable host
* strings. If the target cookie is a domain cookie, a leading
* dot must be present.
* @param aName The name specified in the cookie
* @param aPath The path for which the cookie was set
+ * @param aOriginAttributes The originAttributes of this cookie
* @param aBlocked Indicates if cookies from this host should be permanently blocked
*
*/
- void remove(in AUTF8String aHost,
- in ACString aName,
- in AUTF8String aPath,
- in boolean aBlocked);
+ [implicit_jscontext]
+ void remove(in AUTF8String aHost,
+ in ACString aName,
+ in AUTF8String aPath,
+ in jsval aOriginAttributes,
+ in boolean aBlocked);
};
--- a/netwerk/test/TestCookie.cpp
+++ b/netwerk/test/TestCookie.cpp
@@ -670,17 +670,19 @@ main(int32_t argc, char *argv[])
hostCookies == 2;
// check CookieExists() using the third cookie
bool found;
rv[9] = NS_SUCCEEDED(cookieMgr2->CookieExists(newDomainCookie, &found)) && found;
// remove the cookie, block it, and ensure it can't be added again
rv[10] = NS_SUCCEEDED(cookieMgr->Remove(NS_LITERAL_CSTRING("new.domain"), // domain
NS_LITERAL_CSTRING("test3"), // name
NS_LITERAL_CSTRING("/rabbit"), // path
- true)); // is blocked
+ JS::NullHandleValue, // originAttributes
+ true, // is blocked
+ nullptr)); // JSContext
rv[11] = NS_SUCCEEDED(cookieMgr2->CookieExists(newDomainCookie, &found)) && !found;
rv[12] = NS_SUCCEEDED(cookieMgr2->Add(NS_LITERAL_CSTRING("new.domain"), // domain
NS_LITERAL_CSTRING("/rabbit"), // path
NS_LITERAL_CSTRING("test3"), // name
NS_LITERAL_CSTRING("yes"), // value
false, // is secure
false, // is httponly
true, // is session
--- a/netwerk/test/moz.build
+++ b/netwerk/test/moz.build
@@ -47,9 +47,11 @@ CppUnitTests([
'TestUDPSocket',
])
RESOURCE_FILES += [
'urlparse.dat',
'urlparse_unx.dat',
]
+USE_LIBS += ['static:js']
+
CXXFLAGS += CONFIG['TK_CFLAGS']