Bug 1498370 - Update the storage access flag when storage access is granted/denied r=baku

Differential Revision: https://phabricator.services.mozilla.com/D8550

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ehsan Akhgari 2018-10-15 10:29:33 +00:00
Родитель 8e9e5f75ac
Коммит ecd5aada04
5 изменённых файлов: 109 добавлений и 25 удалений

Просмотреть файл

@ -13669,31 +13669,6 @@ nsIDocument::HasStorageAccess(mozilla::ErrorResult& aRv)
return promise.forget();
}
if (AntiTrackingCommon::ShouldHonorContentBlockingCookieRestrictions() &&
StaticPrefs::network_cookie_cookieBehavior() ==
nsICookieService::BEHAVIOR_REJECT_TRACKER) {
// If we need to abide by Content Blocking cookie restrictions, ensure to
// first do all of our storage access checks. If storage access isn't
// disabled in our document, given that we're a third-party, we must either
// not be a tracker, or be whitelisted for some reason (e.g. a storage
// access permission being granted). In that case, resolve the promise and
// say we have obtained storage access.
if (!nsContentUtils::StorageDisabledByAntiTracking(this, nullptr)) {
// Note, storage might be allowed because the top-level document is on
// the content blocking allowlist! In that case, don't provide special
// treatment here.
bool isOnAllowList = false;
if (NS_SUCCEEDED(AntiTrackingCommon::IsOnContentBlockingAllowList(
topLevelDoc->GetDocumentURI(),
AntiTrackingCommon::eStorageChecks,
isOnAllowList)) &&
!isOnAllowList) {
promise->MaybeResolve(true);
return promise.forget();
}
}
}
nsPIDOMWindowInner* inner = GetInnerWindow();
nsGlobalWindowOuter* outer = nullptr;
if (inner) {

Просмотреть файл

@ -18,6 +18,8 @@
#include "nsDOMNavigationTiming.h"
#include "nsICookieService.h"
#include "nsIDOMStorageManager.h"
#include "nsIPermission.h"
#include "nsIPermissionManager.h"
#include "nsISecureBrowserUI.h"
#include "nsIWebProgressListener.h"
#include "mozilla/AntiTrackingCommon.h"
@ -978,6 +980,11 @@ nsGlobalWindowOuter::~nsGlobalWindowOuter()
if (ac)
ac->RemoveWindowAsListener(this);
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, PERM_CHANGE_NOTIFICATION);
}
nsLayoutStatics::Release();
}
@ -1089,6 +1096,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindowOuter)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMChromeWindow, IsChromeWindow())
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_END
@ -6802,6 +6810,56 @@ nsGlobalWindowOuter::GetInterface(const nsIID & aIID, void **aSink)
return rv;
}
//*****************************************************************************
// nsGlobalWindowOuter::nsIObserver
//*****************************************************************************
NS_IMETHODIMP
nsGlobalWindowOuter::Observe(nsISupports* aSupports, const char* aTopic,
const char16_t* aData)
{
if (!nsCRT::strcmp(aTopic, PERM_CHANGE_NOTIFICATION)) {
if (!nsCRT::strcmp(aData, u"cleared") && !aSupports) {
// All permissions have been cleared.
mHasStorageAccess = false;
return NS_OK;
}
nsCOMPtr<nsIPermission> permission = do_QueryInterface(aSupports);
if (!permission) {
return NS_OK;
}
nsIPrincipal* principal = GetPrincipal();
if (!principal) {
return NS_OK;
}
if (!AntiTrackingCommon::IsStorageAccessPermission(permission, principal)) {
return NS_OK;
}
if (!nsCRT::strcmp(aData, u"deleted")) {
// The storage access permission was deleted.
mHasStorageAccess = false;
return NS_OK;
}
if (!nsCRT::strcmp(aData, u"added") ||
!nsCRT::strcmp(aData, u"changed")) {
// The storage access permission was granted or modified.
uint32_t expireType = 0;
int64_t expireTime = 0;
MOZ_ALWAYS_SUCCEEDS(permission->GetExpireType(&expireType));
MOZ_ALWAYS_SUCCEEDS(permission->GetExpireTime(&expireTime));
if ((expireType == nsIPermissionManager::EXPIRE_TIME &&
expireTime >= PR_Now() / 1000) ||
(expireType == nsIPermissionManager::EXPIRE_SESSION &&
expireTime != 0)) {
// Permission hasn't expired yet.
mHasStorageAccess = true;
return NS_OK;
}
}
}
return NS_OK;
}
bool
nsGlobalWindowOuter::IsSuspended() const
{
@ -7673,6 +7731,10 @@ nsGlobalWindowOuter::Create(nsIDocShell* aDocShell, bool aIsChrome)
window->SetDocShell(aDocShell);
window->InitWasOffline();
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->AddObserver(window, PERM_CHANGE_NOTIFICATION, true);
}
return window.forget();
}

Просмотреть файл

@ -27,6 +27,7 @@
#include "nsIBrowserDOMWindow.h"
#include "nsIInterfaceRequestor.h"
#include "nsIDOMChromeWindow.h"
#include "nsIObserver.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsITimer.h"
@ -172,6 +173,7 @@ class nsGlobalWindowOuter final
, public nsSupportsWeakReference
, public nsIInterfaceRequestor
, public PRCListStr
, public nsIObserver
{
public:
typedef nsDataHashtable<nsUint64HashKey, nsGlobalWindowOuter*> OuterWindowByIdTable;
@ -361,6 +363,9 @@ public:
// nsIInterfaceRequestor
NS_DECL_NSIINTERFACEREQUESTOR
// nsIObserver
NS_DECL_NSIOBSERVER
already_AddRefed<nsPIDOMWindowOuter> IndexedGetterOuter(uint32_t aIndex);
already_AddRefed<nsPIDOMWindowOuter> GetTop() override;

Просмотреть файл

@ -564,6 +564,42 @@ AntiTrackingCommon::SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess(n
LOG(("Result: %s", NS_SUCCEEDED(rv) ? "success" : "failure"));
}
// static
bool
AntiTrackingCommon::IsStorageAccessPermission(nsIPermission* aPermission,
nsIPrincipal* aPrincipal)
{
MOZ_ASSERT(aPermission);
MOZ_ASSERT(aPrincipal);
nsAutoCString origin;
nsresult rv = aPrincipal->GetOriginNoSuffix(origin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
// The permission key may belong either to a tracking origin on the same
// origin as the granted origin, or on another origin as the granted origin
// (for example when a tracker in a third-party context uses window.open to
// open another origin where that second origin would be the granted origin.)
// But even in the second case, the type of the permission would still be
// formed by concatenating the granted origin to the end of the type name
// (see CreatePermissionKey). Therefore, we pass in the same argument to
// both tracking origin and granted origin here in order to compute the
// shorter permission key and will then do a prefix match on the type of the
// input permission to see if it is a storage access permission or not.
nsAutoCString permissionKey;
CreatePermissionKey(origin, origin, permissionKey);
nsAutoCString type;
rv = aPermission->GetType(type);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
return StringBeginsWith(type, permissionKey);
}
bool
AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(nsPIDOMWindowInner* aWindow,
nsIURI* aURI,

Просмотреть файл

@ -13,6 +13,7 @@
class nsIChannel;
class nsIHttpChannel;
class nsIPermission;
class nsIPrincipal;
class nsIURI;
class nsPIDOMWindowInner;
@ -108,6 +109,11 @@ public:
nsPIDOMWindowInner* aParentWindow,
StorageAccessGrantedReason aReason);
// Returns true if the permission passed in is a storage access permission
// for the passed in principal argument.
static bool
IsStorageAccessPermission(nsIPermission* aPermission, nsIPrincipal* aPrincipal);
static void
StoreUserInteractionFor(nsIPrincipal* aPrincipal);