Bug 1268726 - isolate shared worker by first party domain. r=baku

Tor 15564: Isolate SharedWorker by first party domain
uplift/refactor by Dave Huseby <dhuseby@mozilla.com>

review tweaks
This commit is contained in:
Arthur Edelstein 2016-09-19 21:13:00 -04:00
Родитель 7784aa2e51
Коммит dfebfaa34a
11 изменённых файлов: 96 добавлений и 37 удалений

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

@ -3097,6 +3097,48 @@ nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
return NS_FAILED(rv) ? false : NS_CP_ACCEPTED(decision); return NS_FAILED(rv) ? false : NS_CP_ACCEPTED(decision);
} }
// static
mozilla::PrincipalOriginAttributes
nsContentUtils::GetOriginAttributes(nsIDocument* aDocument)
{
if (!aDocument) {
return mozilla::PrincipalOriginAttributes();
}
nsCOMPtr<nsILoadGroup> loadGroup = aDocument->GetDocumentLoadGroup();
if (loadGroup) {
return GetOriginAttributes(loadGroup);
}
mozilla::PrincipalOriginAttributes attrs;
mozilla::NeckoOriginAttributes nattrs;
nsCOMPtr<nsIChannel> channel = aDocument->GetChannel();
if (channel && NS_GetOriginAttributes(channel, nattrs)) {
attrs.InheritFromNecko(nattrs);
}
return attrs;
}
// static
mozilla::PrincipalOriginAttributes
nsContentUtils::GetOriginAttributes(nsILoadGroup* aLoadGroup)
{
if (!aLoadGroup) {
return mozilla::PrincipalOriginAttributes();
}
mozilla::PrincipalOriginAttributes attrs;
mozilla::DocShellOriginAttributes dsattrs;
nsCOMPtr<nsIInterfaceRequestor> callbacks;
aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
if (callbacks) {
nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
if (loadContext && loadContext->GetOriginAttributes(dsattrs)) {
attrs.InheritFromDocShellToDoc(dsattrs, nullptr);
}
}
return attrs;
}
// static // static
bool bool
nsContentUtils::IsInPrivateBrowsing(nsIDocument* aDoc) nsContentUtils::IsInPrivateBrowsing(nsIDocument* aDoc)

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

@ -785,6 +785,18 @@ public:
bool aIsForWindow, bool aIsForWindow,
uint32_t *aArgCount, const char*** aArgNames); uint32_t *aArgCount, const char*** aArgNames);
/**
* Returns origin attributes of the document.
**/
static mozilla::PrincipalOriginAttributes
GetOriginAttributes(nsIDocument* aDoc);
/**
* Returns origin attributes of the load group.
**/
static mozilla::PrincipalOriginAttributes
GetOriginAttributes(nsILoadGroup* aLoadGroup);
/** /**
* Returns true if this document is in a Private Browsing window. * Returns true if this document is in a Private Browsing window.
*/ */

2
dom/cache/CacheStorage.cpp поставляемый
Просмотреть файл

@ -196,7 +196,7 @@ CacheStorage::CreateOnWorker(Namespace aNamespace, nsIGlobalObject* aGlobal,
return ref.forget(); return ref.forget();
} }
if (aWorkerPrivate->IsInPrivateBrowsing()) { if (aWorkerPrivate->GetOriginAttributes().mPrivateBrowsingId > 0) {
NS_WARNING("CacheStorage not supported during private browsing."); NS_WARNING("CacheStorage not supported during private browsing.");
RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR); RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR);
return ref.forget(); return ref.forget();

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

@ -245,29 +245,24 @@ GetWorkerPref(const nsACString& aPref,
return result; return result;
} }
// This function creates a key for a SharedWorker composed by "name|scriptSpec". // This fn creates a key for a SharedWorker that contains the name, script
// If the name contains a '|', this will be replaced by '||'. // spec, and the serialized origin attributes:
// "name|scriptSpec^key1=val1&key2=val2&key3=val3"
void void
GenerateSharedWorkerKey(const nsACString& aScriptSpec, const nsACString& aName, GenerateSharedWorkerKey(const nsACString& aScriptSpec,
bool aPrivateBrowsing, nsCString& aKey) const nsACString& aName,
const PrincipalOriginAttributes& aAttrs,
nsCString& aKey)
{ {
nsAutoCString suffix;
aAttrs.CreateSuffix(suffix);
aKey.Truncate(); aKey.Truncate();
aKey.SetCapacity(aScriptSpec.Length() + aName.Length() + 3); aKey.SetCapacity(aName.Length() + aScriptSpec.Length() + suffix.Length() + 2);
aKey.Append(aPrivateBrowsing ? "1|" : "0|"); aKey.Append(aName);
nsACString::const_iterator start, end;
aName.BeginReading(start);
aName.EndReading(end);
for (; start != end; ++start) {
if (*start == '|') {
aKey.AppendASCII("||");
} else {
aKey.Append(*start);
}
}
aKey.Append('|'); aKey.Append('|');
aKey.Append(aScriptSpec); aKey.Append(aScriptSpec);
aKey.Append(suffix);
} }
void void
@ -1641,7 +1636,7 @@ RuntimeService::RegisterWorker(WorkerPrivate* aWorkerPrivate)
const nsCString& sharedWorkerName = aWorkerPrivate->WorkerName(); const nsCString& sharedWorkerName = aWorkerPrivate->WorkerName();
nsAutoCString key; nsAutoCString key;
GenerateSharedWorkerKey(sharedWorkerScriptSpec, sharedWorkerName, GenerateSharedWorkerKey(sharedWorkerScriptSpec, sharedWorkerName,
aWorkerPrivate->IsInPrivateBrowsing(), key); aWorkerPrivate->GetOriginAttributes(), key);
MOZ_ASSERT(!domainInfo->mSharedWorkerInfos.Get(key)); MOZ_ASSERT(!domainInfo->mSharedWorkerInfos.Get(key));
SharedWorkerInfo* sharedWorkerInfo = SharedWorkerInfo* sharedWorkerInfo =
@ -1718,7 +1713,7 @@ RuntimeService::RemoveSharedWorker(WorkerDomainInfo* aDomainInfo,
#ifdef DEBUG #ifdef DEBUG
nsAutoCString key; nsAutoCString key;
GenerateSharedWorkerKey(data->mScriptSpec, data->mName, GenerateSharedWorkerKey(data->mScriptSpec, data->mName,
aWorkerPrivate->IsInPrivateBrowsing(), key); aWorkerPrivate->GetOriginAttributes(), key);
MOZ_ASSERT(iter.Key() == key); MOZ_ASSERT(iter.Key() == key);
#endif #endif
iter.Remove(); iter.Remove();
@ -2434,9 +2429,10 @@ RuntimeService::CreateSharedWorkerFromLoadInfo(JSContext* aCx,
nsresult rv = aLoadInfo->mResolvedScriptURI->GetSpec(scriptSpec); nsresult rv = aLoadInfo->mResolvedScriptURI->GetSpec(scriptSpec);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(aLoadInfo->mPrincipal);
nsAutoCString key; nsAutoCString key;
GenerateSharedWorkerKey(scriptSpec, aName, GenerateSharedWorkerKey(scriptSpec, aName,
aLoadInfo->mPrivateBrowsing, key); BasePrincipal::Cast(aLoadInfo->mPrincipal)->OriginAttributesRef(), key);
if (mDomainMap.Get(aLoadInfo->mDomain, &domainInfo) && if (mDomainMap.Get(aLoadInfo->mDomain, &domainInfo) &&
domainInfo->mSharedWorkerInfos.Get(key, &sharedWorkerInfo)) { domainInfo->mSharedWorkerInfos.Get(key, &sharedWorkerInfo)) {

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

@ -350,7 +350,7 @@ public:
explicit CacheCreator(WorkerPrivate* aWorkerPrivate) explicit CacheCreator(WorkerPrivate* aWorkerPrivate)
: mCacheName(aWorkerPrivate->ServiceWorkerCacheName()) : mCacheName(aWorkerPrivate->ServiceWorkerCacheName())
, mPrivateBrowsing(aWorkerPrivate->IsInPrivateBrowsing()) , mOriginAttributes(aWorkerPrivate->GetOriginAttributes())
{ {
MOZ_ASSERT(aWorkerPrivate->IsServiceWorker()); MOZ_ASSERT(aWorkerPrivate->IsServiceWorker());
MOZ_ASSERT(aWorkerPrivate->LoadScriptAsPartOfLoadingServiceWorkerScript()); MOZ_ASSERT(aWorkerPrivate->LoadScriptAsPartOfLoadingServiceWorkerScript());
@ -411,7 +411,7 @@ private:
nsTArray<RefPtr<CacheScriptLoader>> mLoaders; nsTArray<RefPtr<CacheScriptLoader>> mLoaders;
nsString mCacheName; nsString mCacheName;
bool mPrivateBrowsing; PrincipalOriginAttributes mOriginAttributes;
}; };
NS_IMPL_ISUPPORTS0(CacheCreator) NS_IMPL_ISUPPORTS0(CacheCreator)
@ -1467,7 +1467,7 @@ CacheCreator::CreateCacheStorage(nsIPrincipal* aPrincipal)
// If we're in private browsing mode, don't even try to create the // If we're in private browsing mode, don't even try to create the
// CacheStorage. Instead, just fail immediately to terminate the // CacheStorage. Instead, just fail immediately to terminate the
// ServiceWorker load. // ServiceWorker load.
if (NS_WARN_IF(mPrivateBrowsing)) { if (NS_WARN_IF(mOriginAttributes.mPrivateBrowsingId > 0)) {
return NS_ERROR_DOM_SECURITY_ERR; return NS_ERROR_DOM_SECURITY_ERR;
} }
@ -1478,7 +1478,8 @@ CacheCreator::CreateCacheStorage(nsIPrincipal* aPrincipal)
mCacheStorage = mCacheStorage =
CacheStorage::CreateOnMainThread(mozilla::dom::cache::CHROME_ONLY_NAMESPACE, CacheStorage::CreateOnMainThread(mozilla::dom::cache::CHROME_ONLY_NAMESPACE,
mSandboxGlobalObject, mSandboxGlobalObject,
aPrincipal, mPrivateBrowsing, aPrincipal,
false, /* privateBrowsing can't be true here */
true /* force trusted origin */, true /* force trusted origin */,
error); error);
if (NS_WARN_IF(error.Failed())) { if (NS_WARN_IF(error.Failed())) {

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

@ -160,6 +160,8 @@ ServiceWorkerInfo::ServiceWorkerInfo(nsIPrincipal* aPrincipal,
, mSkipWaitingFlag(false) , mSkipWaitingFlag(false)
{ {
MOZ_ASSERT(mPrincipal); MOZ_ASSERT(mPrincipal);
// cache origin attributes so we can use them off main thread
mOriginAttributes = BasePrincipal::Cast(mPrincipal)->OriginAttributesRef();
MOZ_ASSERT(!mScope.IsEmpty()); MOZ_ASSERT(!mScope.IsEmpty());
MOZ_ASSERT(!mScriptSpec.IsEmpty()); MOZ_ASSERT(!mScriptSpec.IsEmpty());
MOZ_ASSERT(!mCacheName.IsEmpty()); MOZ_ASSERT(!mCacheName.IsEmpty());

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

@ -31,6 +31,7 @@ private:
const nsCString mScriptSpec; const nsCString mScriptSpec;
const nsString mCacheName; const nsString mCacheName;
ServiceWorkerState mState; ServiceWorkerState mState;
PrincipalOriginAttributes mOriginAttributes;
// This id is shared with WorkerPrivate to match requests issued by service // This id is shared with WorkerPrivate to match requests issued by service
// workers to their corresponding serviceWorkerInfo. // workers to their corresponding serviceWorkerInfo.
@ -104,6 +105,12 @@ public:
return mState; return mState;
} }
const PrincipalOriginAttributes&
GetOriginAttributes() const
{
return mOriginAttributes;
}
const nsString& const nsString&
CacheName() const CacheName() const
{ {

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

@ -1714,7 +1714,7 @@ ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
nsContentUtils::StorageAccess access = nsContentUtils::StorageAccess access =
nsContentUtils::StorageAllowedForPrincipal(info.mPrincipal); nsContentUtils::StorageAllowedForPrincipal(info.mPrincipal);
info.mStorageAllowed = access > nsContentUtils::StorageAccess::ePrivateBrowsing; info.mStorageAllowed = access > nsContentUtils::StorageAccess::ePrivateBrowsing;
info.mPrivateBrowsing = false; info.mOriginAttributes = mInfo->GetOriginAttributes();
nsCOMPtr<nsIContentSecurityPolicy> csp; nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = info.mPrincipal->GetCsp(getter_AddRefs(csp)); rv = info.mPrincipal->GetCsp(getter_AddRefs(csp));

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

@ -1739,7 +1739,6 @@ WorkerLoadInfo::WorkerLoadInfo()
, mXHRParamsAllowed(false) , mXHRParamsAllowed(false)
, mPrincipalIsSystem(false) , mPrincipalIsSystem(false)
, mStorageAllowed(false) , mStorageAllowed(false)
, mPrivateBrowsing(true)
, mServiceWorkersTestingInWindow(false) , mServiceWorkersTestingInWindow(false)
{ {
MOZ_COUNT_CTOR(WorkerLoadInfo); MOZ_COUNT_CTOR(WorkerLoadInfo);
@ -1797,8 +1796,8 @@ WorkerLoadInfo::StealFrom(WorkerLoadInfo& aOther)
mXHRParamsAllowed = aOther.mXHRParamsAllowed; mXHRParamsAllowed = aOther.mXHRParamsAllowed;
mPrincipalIsSystem = aOther.mPrincipalIsSystem; mPrincipalIsSystem = aOther.mPrincipalIsSystem;
mStorageAllowed = aOther.mStorageAllowed; mStorageAllowed = aOther.mStorageAllowed;
mPrivateBrowsing = aOther.mPrivateBrowsing;
mServiceWorkersTestingInWindow = aOther.mServiceWorkersTestingInWindow; mServiceWorkersTestingInWindow = aOther.mServiceWorkersTestingInWindow;
mOriginAttributes = aOther.mOriginAttributes;
} }
template <class Derived> template <class Derived>
@ -3426,7 +3425,7 @@ WorkerPrivateParent<Derived>::SetPrincipal(nsIPrincipal* aPrincipal,
mLoadInfo.mLoadGroup = aLoadGroup; mLoadInfo.mLoadGroup = aLoadGroup;
mLoadInfo.mPrincipalInfo = new PrincipalInfo(); mLoadInfo.mPrincipalInfo = new PrincipalInfo();
mLoadInfo.mPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(aLoadGroup); mLoadInfo.mOriginAttributes = nsContentUtils::GetOriginAttributes(aLoadGroup);
MOZ_ALWAYS_SUCCEEDS( MOZ_ALWAYS_SUCCEEDS(
PrincipalToPrincipalInfo(aPrincipal, mLoadInfo.mPrincipalInfo)); PrincipalToPrincipalInfo(aPrincipal, mLoadInfo.mPrincipalInfo));
@ -4193,7 +4192,7 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindowInner* aWindow,
loadInfo.mFromWindow = aParent->IsFromWindow(); loadInfo.mFromWindow = aParent->IsFromWindow();
loadInfo.mWindowID = aParent->WindowID(); loadInfo.mWindowID = aParent->WindowID();
loadInfo.mStorageAllowed = aParent->IsStorageAllowed(); loadInfo.mStorageAllowed = aParent->IsStorageAllowed();
loadInfo.mPrivateBrowsing = aParent->IsInPrivateBrowsing(); loadInfo.mOriginAttributes = aParent->GetOriginAttributes();
loadInfo.mServiceWorkersTestingInWindow = loadInfo.mServiceWorkersTestingInWindow =
aParent->ServiceWorkersTestingInWindow(); aParent->ServiceWorkersTestingInWindow();
} else { } else {
@ -4317,7 +4316,7 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindowInner* aWindow,
nsContentUtils::StorageAccess access = nsContentUtils::StorageAccess access =
nsContentUtils::StorageAllowedForWindow(globalWindow); nsContentUtils::StorageAllowedForWindow(globalWindow);
loadInfo.mStorageAllowed = access > nsContentUtils::StorageAccess::eDeny; loadInfo.mStorageAllowed = access > nsContentUtils::StorageAccess::eDeny;
loadInfo.mPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(document); loadInfo.mOriginAttributes = nsContentUtils::GetOriginAttributes(document);
} else { } else {
// Not a window // Not a window
MOZ_ASSERT(isChrome); MOZ_ASSERT(isChrome);
@ -4359,7 +4358,7 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindowInner* aWindow,
loadInfo.mFromWindow = false; loadInfo.mFromWindow = false;
loadInfo.mWindowID = UINT64_MAX; loadInfo.mWindowID = UINT64_MAX;
loadInfo.mStorageAllowed = true; loadInfo.mStorageAllowed = true;
loadInfo.mPrivateBrowsing = false; loadInfo.mOriginAttributes = PrincipalOriginAttributes();
} }
MOZ_ASSERT(loadInfo.mPrincipal); MOZ_ASSERT(loadInfo.mPrincipal);

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

@ -783,10 +783,10 @@ public:
return mLoadInfo.mStorageAllowed; return mLoadInfo.mStorageAllowed;
} }
bool const PrincipalOriginAttributes&
IsInPrivateBrowsing() const GetOriginAttributes() const
{ {
return mLoadInfo.mPrivateBrowsing; return mLoadInfo.mOriginAttributes;
} }
// Determine if the SW testing per-window flag is set by devtools // Determine if the SW testing per-window flag is set by devtools

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

@ -269,8 +269,8 @@ struct WorkerLoadInfo
bool mXHRParamsAllowed; bool mXHRParamsAllowed;
bool mPrincipalIsSystem; bool mPrincipalIsSystem;
bool mStorageAllowed; bool mStorageAllowed;
bool mPrivateBrowsing;
bool mServiceWorkersTestingInWindow; bool mServiceWorkersTestingInWindow;
PrincipalOriginAttributes mOriginAttributes;
WorkerLoadInfo(); WorkerLoadInfo();
~WorkerLoadInfo(); ~WorkerLoadInfo();