зеркало из https://github.com/mozilla/gecko-dev.git
Bug 536509 - Update localStorage to use common StorageAllowedForWindow logic, r=ehsan
This commit is contained in:
Родитель
868a200adc
Коммит
c84994fb3c
|
@ -10910,7 +10910,7 @@ nsGlobalWindow::GetLocalStorage(ErrorResult& aError)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mLocalStorage) {
|
if (!mLocalStorage) {
|
||||||
if (!DOMStorage::CanUseStorage()) {
|
if (!DOMStorage::CanUseStorage(this)) {
|
||||||
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -10928,13 +10928,6 @@ nsGlobalWindow::GetLocalStorage(ErrorResult& aError)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the document has the sandboxed origin flag set
|
|
||||||
// don't allow access to localStorage.
|
|
||||||
if (mDoc && (mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN)) {
|
|
||||||
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsString documentURI;
|
nsString documentURI;
|
||||||
if (mDoc) {
|
if (mDoc) {
|
||||||
mDoc->GetDocumentURI(documentURI);
|
mDoc->GetDocumentURI(documentURI);
|
||||||
|
|
|
@ -13,13 +13,14 @@
|
||||||
#include "nsIPermissionManager.h"
|
#include "nsIPermissionManager.h"
|
||||||
#include "nsIPrincipal.h"
|
#include "nsIPrincipal.h"
|
||||||
#include "nsICookiePermission.h"
|
#include "nsICookiePermission.h"
|
||||||
#include "nsICookieService.h"
|
#include "nsPIDOMWindow.h"
|
||||||
|
|
||||||
#include "mozilla/dom/StorageBinding.h"
|
#include "mozilla/dom/StorageBinding.h"
|
||||||
#include "mozilla/dom/StorageEvent.h"
|
#include "mozilla/dom/StorageEvent.h"
|
||||||
#include "mozilla/dom/StorageEventBinding.h"
|
#include "mozilla/dom/StorageEventBinding.h"
|
||||||
#include "mozilla/Services.h"
|
#include "mozilla/Services.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
|
#include "mozilla/EnumSet.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsServiceManagerUtils.h"
|
#include "nsServiceManagerUtils.h"
|
||||||
|
@ -70,7 +71,7 @@ DOMStorage::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||||
uint32_t
|
uint32_t
|
||||||
DOMStorage::GetLength(ErrorResult& aRv)
|
DOMStorage::GetLength(ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
if (!CanUseStorage(this)) {
|
if (!CanUseStorage(nullptr, this)) {
|
||||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +84,7 @@ DOMStorage::GetLength(ErrorResult& aRv)
|
||||||
void
|
void
|
||||||
DOMStorage::Key(uint32_t aIndex, nsAString& aResult, ErrorResult& aRv)
|
DOMStorage::Key(uint32_t aIndex, nsAString& aResult, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
if (!CanUseStorage(this)) {
|
if (!CanUseStorage(nullptr, this)) {
|
||||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -94,7 +95,7 @@ DOMStorage::Key(uint32_t aIndex, nsAString& aResult, ErrorResult& aRv)
|
||||||
void
|
void
|
||||||
DOMStorage::GetItem(const nsAString& aKey, nsAString& aResult, ErrorResult& aRv)
|
DOMStorage::GetItem(const nsAString& aKey, nsAString& aResult, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
if (!CanUseStorage(this)) {
|
if (!CanUseStorage(nullptr, this)) {
|
||||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +107,7 @@ void
|
||||||
DOMStorage::SetItem(const nsAString& aKey, const nsAString& aData,
|
DOMStorage::SetItem(const nsAString& aKey, const nsAString& aData,
|
||||||
ErrorResult& aRv)
|
ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
if (!CanUseStorage(this)) {
|
if (!CanUseStorage(nullptr, this)) {
|
||||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -139,7 +140,7 @@ DOMStorage::SetItem(const nsAString& aKey, const nsAString& aData,
|
||||||
void
|
void
|
||||||
DOMStorage::RemoveItem(const nsAString& aKey, ErrorResult& aRv)
|
DOMStorage::RemoveItem(const nsAString& aKey, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
if (!CanUseStorage(this)) {
|
if (!CanUseStorage(nullptr, this)) {
|
||||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -158,7 +159,7 @@ DOMStorage::RemoveItem(const nsAString& aKey, ErrorResult& aRv)
|
||||||
void
|
void
|
||||||
DOMStorage::Clear(ErrorResult& aRv)
|
DOMStorage::Clear(ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
if (!CanUseStorage(this)) {
|
if (!CanUseStorage(nullptr, this)) {
|
||||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -236,60 +237,32 @@ static const char kCookiesLifetimePolicy[] = "network.cookie.lifetimePolicy";
|
||||||
|
|
||||||
// static, public
|
// static, public
|
||||||
bool
|
bool
|
||||||
DOMStorage::CanUseStorage(DOMStorage* aStorage)
|
DOMStorage::CanUseStorage(nsPIDOMWindow* aWindow, DOMStorage* aStorage)
|
||||||
{
|
{
|
||||||
// This method is responsible for correct setting of mIsSessionOnly.
|
// This method is responsible for correct setting of mIsSessionOnly.
|
||||||
// It doesn't work with mIsPrivate flag at all, since it is checked
|
// It doesn't work with mIsPrivate flag at all, since it is checked
|
||||||
// regardless mIsSessionOnly flag in DOMStorageCache code.
|
// regardless mIsSessionOnly flag in DOMStorageCache code.
|
||||||
if (aStorage) {
|
|
||||||
aStorage->mIsSessionOnly = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mozilla::Preferences::GetBool(kStorageEnabled)) {
|
if (!mozilla::Preferences::GetBool(kStorageEnabled)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// chrome can always use aStorage regardless of permission preferences
|
nsContentUtils::StorageAccess access = nsContentUtils::StorageAccess::eDeny;
|
||||||
nsCOMPtr<nsIPrincipal> subjectPrincipal =
|
if (aWindow) {
|
||||||
nsContentUtils::SubjectPrincipal();
|
access = nsContentUtils::StorageAllowedForWindow(aWindow);
|
||||||
if (nsContentUtils::IsSystemPrincipal(subjectPrincipal)) {
|
} else if (aStorage) {
|
||||||
return true;
|
access = nsContentUtils::StorageAllowedForPrincipal(aStorage->mPrincipal);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIPermissionManager> permissionManager =
|
if (access == nsContentUtils::StorageAccess::eDeny) {
|
||||||
services::GetPermissionManager();
|
|
||||||
if (!permissionManager) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t perm;
|
|
||||||
permissionManager->TestPermissionFromPrincipal(subjectPrincipal,
|
|
||||||
kPermissionType, &perm);
|
|
||||||
|
|
||||||
if (perm == nsIPermissionManager::DENY_ACTION) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (perm == nsICookiePermission::ACCESS_SESSION) {
|
|
||||||
if (aStorage) {
|
|
||||||
aStorage->mIsSessionOnly = true;
|
|
||||||
}
|
|
||||||
} else if (perm != nsIPermissionManager::ALLOW_ACTION) {
|
|
||||||
uint32_t cookieBehavior = Preferences::GetUint(kCookiesBehavior);
|
|
||||||
uint32_t lifetimePolicy = Preferences::GetUint(kCookiesLifetimePolicy);
|
|
||||||
|
|
||||||
// Treat "ask every time" as "reject always".
|
|
||||||
if (cookieBehavior == nsICookieService::BEHAVIOR_REJECT ||
|
|
||||||
lifetimePolicy == nsICookieService::ASK_BEFORE_ACCEPT) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lifetimePolicy == nsICookieService::ACCEPT_SESSION && aStorage) {
|
|
||||||
aStorage->mIsSessionOnly = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aStorage) {
|
if (aStorage) {
|
||||||
|
aStorage->mIsSessionOnly = access <= nsContentUtils::StorageAccess::eSessionScoped;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPrincipal> subjectPrincipal =
|
||||||
|
nsContentUtils::SubjectPrincipal();
|
||||||
return aStorage->CanAccess(subjectPrincipal);
|
return aStorage->CanAccess(subjectPrincipal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +300,7 @@ DOMStorage::CanAccess(nsIPrincipal* aPrincipal)
|
||||||
void
|
void
|
||||||
DOMStorage::GetSupportedNames(unsigned, nsTArray<nsString>& aKeys)
|
DOMStorage::GetSupportedNames(unsigned, nsTArray<nsString>& aKeys)
|
||||||
{
|
{
|
||||||
if (!CanUseStorage(this)) {
|
if (!CanUseStorage(nullptr, this)) {
|
||||||
// return just an empty array
|
// return just an empty array
|
||||||
aKeys.Clear();
|
aKeys.Clear();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
class nsIPrincipal;
|
class nsIPrincipal;
|
||||||
class nsIDOMWindow;
|
class nsIDOMWindow;
|
||||||
|
class nsPIDOMWindow;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
@ -122,7 +123,7 @@ public:
|
||||||
// It is an optimization since the privileges check and session only
|
// It is an optimization since the privileges check and session only
|
||||||
// state determination are complex and share the code (comes hand in
|
// state determination are complex and share the code (comes hand in
|
||||||
// hand together).
|
// hand together).
|
||||||
static bool CanUseStorage(DOMStorage* aStorage = nullptr);
|
static bool CanUseStorage(nsPIDOMWindow* aWindow, DOMStorage* aStorage = nullptr);
|
||||||
|
|
||||||
bool IsPrivate() const { return mIsPrivate; }
|
bool IsPrivate() const { return mIsPrivate; }
|
||||||
bool IsSessionOnly() const { return mIsSessionOnly; }
|
bool IsSessionOnly() const { return mIsSessionOnly; }
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>localStorage cookies settings test</title>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="interOriginFrame.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript">
|
||||||
|
try {
|
||||||
|
localStorage.setItem("contentkey", "test-value");
|
||||||
|
ok(false, "Setting localStorageItem should throw a security exception");
|
||||||
|
} catch(ex) {
|
||||||
|
is(ex.name, "SecurityError");
|
||||||
|
}
|
||||||
|
|
||||||
|
finishTest();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -49,7 +49,9 @@ function todo(a, b, message)
|
||||||
|
|
||||||
function finishTest()
|
function finishTest()
|
||||||
{
|
{
|
||||||
localStorage.clear();
|
try {
|
||||||
|
localStorage.clear();
|
||||||
|
} catch (e) {}
|
||||||
postMsg("done");
|
postMsg("done");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
support-files =
|
support-files =
|
||||||
frameAppIsolation.html
|
frameAppIsolation.html
|
||||||
frameChromeSlave.html
|
frameChromeSlave.html
|
||||||
|
frameLocalStorageCookieSettings.html
|
||||||
frameKeySync.html
|
frameKeySync.html
|
||||||
frameMasterEqual.html
|
frameMasterEqual.html
|
||||||
frameMasterNotEqual.html
|
frameMasterNotEqual.html
|
||||||
|
|
|
@ -3,8 +3,13 @@
|
||||||
<title>localStorage cookies settings test</title>
|
<title>localStorage cookies settings test</title>
|
||||||
|
|
||||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="text/javascript" src="interOriginTest.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe></iframe>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
@ -37,11 +42,33 @@ function test2() {
|
||||||
is(ex.name, "SecurityError");
|
is(ex.name, "SecurityError");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set cookies behavior to "reject 3rd party"
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 1]],
|
||||||
|
"clear": [["network.cookie.lifetimePolicy"]]},
|
||||||
|
test3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test3() {
|
||||||
|
try {
|
||||||
|
localStorage.setItem("contentkey", "test-value");
|
||||||
|
ok(true, "Setting localStorageItem should not throw a security exception");
|
||||||
|
}
|
||||||
|
catch(ex) {
|
||||||
|
ok(false, "Setting localStorageItem should not throw a security exception");
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileTest = (location.protocol + "//example.com" + location.pathname)
|
||||||
|
.replace("test_l", "frameL");
|
||||||
|
|
||||||
|
var myframe = document.querySelector("iframe");
|
||||||
|
myframe.src = fileTest;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by interOriginTest.js
|
||||||
|
function doNextTest() {
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Загрузка…
Ссылка в новой задаче