mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-27 02:47:31 +09:00
Merge remote-tracking branch 'origin/tracking' into custom
This commit is contained in:
commit
80c4f1d745
79 changed files with 1353 additions and 509 deletions
|
|
@ -135,6 +135,7 @@ NS_CP_ContentTypeName(uint32_t contentType)
|
|||
CASE_RETURN( TYPE_INTERNAL_STYLESHEET );
|
||||
CASE_RETURN( TYPE_INTERNAL_STYLESHEET_PRELOAD );
|
||||
CASE_RETURN( TYPE_SAVEAS_DOWNLOAD );
|
||||
CASE_RETURN( TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS );
|
||||
default:
|
||||
return "<Unknown Type>";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2395,34 +2395,35 @@ nsContentUtils::GetCommonAncestor(nsIDOMNode *aNode,
|
|||
return CallQueryInterface(common, aCommonAncestor);
|
||||
}
|
||||
|
||||
// static
|
||||
nsINode*
|
||||
nsContentUtils::GetCommonAncestor(nsINode* aNode1,
|
||||
nsINode* aNode2)
|
||||
template <typename Node, typename GetParentFunc>
|
||||
static Node*
|
||||
GetCommonAncestorInternal(Node* aNode1,
|
||||
Node* aNode2,
|
||||
GetParentFunc aGetParentFunc)
|
||||
{
|
||||
if (aNode1 == aNode2) {
|
||||
return aNode1;
|
||||
}
|
||||
|
||||
// Build the chain of parents
|
||||
AutoTArray<nsINode*, 30> parents1, parents2;
|
||||
AutoTArray<Node*, 30> parents1, parents2;
|
||||
do {
|
||||
parents1.AppendElement(aNode1);
|
||||
aNode1 = aNode1->GetParentNode();
|
||||
aNode1 = aGetParentFunc(aNode1);
|
||||
} while (aNode1);
|
||||
do {
|
||||
parents2.AppendElement(aNode2);
|
||||
aNode2 = aNode2->GetParentNode();
|
||||
aNode2 = aGetParentFunc(aNode2);
|
||||
} while (aNode2);
|
||||
|
||||
// Find where the parent chain differs
|
||||
uint32_t pos1 = parents1.Length();
|
||||
uint32_t pos2 = parents2.Length();
|
||||
nsINode* parent = nullptr;
|
||||
Node* parent = nullptr;
|
||||
uint32_t len;
|
||||
for (len = std::min(pos1, pos2); len > 0; --len) {
|
||||
nsINode* child1 = parents1.ElementAt(--pos1);
|
||||
nsINode* child2 = parents2.ElementAt(--pos2);
|
||||
Node* child1 = parents1.ElementAt(--pos1);
|
||||
Node* child2 = parents2.ElementAt(--pos2);
|
||||
if (child1 != child2) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -2432,6 +2433,25 @@ nsContentUtils::GetCommonAncestor(nsINode* aNode1,
|
|||
return parent;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsINode*
|
||||
nsContentUtils::GetCommonAncestor(nsINode* aNode1, nsINode* aNode2)
|
||||
{
|
||||
return GetCommonAncestorInternal(aNode1, aNode2, [](nsINode* aNode) {
|
||||
return aNode->GetParentNode();
|
||||
});
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsIContent*
|
||||
nsContentUtils::GetCommonFlattenedTreeAncestor(nsIContent* aContent1,
|
||||
nsIContent* aContent2)
|
||||
{
|
||||
return GetCommonAncestorInternal(aContent1, aContent2, [](nsIContent* aContent) {
|
||||
return aContent->GetFlattenedTreeParent();
|
||||
});
|
||||
}
|
||||
|
||||
// static
|
||||
nsINode*
|
||||
nsContentUtils::GetCommonAncestorUnderInteractiveContent(nsINode* aNode1,
|
||||
|
|
@ -8595,6 +8615,7 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType)
|
|||
case nsIContentPolicy::TYPE_INTERNAL_WORKER:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS:
|
||||
return nsIContentPolicy::TYPE_SCRIPT;
|
||||
|
||||
case nsIContentPolicy::TYPE_INTERNAL_EMBED:
|
||||
|
|
|
|||
|
|
@ -333,12 +333,18 @@ public:
|
|||
nsIDOMNode** aCommonAncestor);
|
||||
|
||||
/**
|
||||
* Returns the common ancestor, if any, for two nodes. Returns null if the
|
||||
* nodes are disconnected.
|
||||
* Returns the common ancestor, if any, for two nodes.
|
||||
* Returns null if the nodes are disconnected.
|
||||
*/
|
||||
static nsINode* GetCommonAncestor(nsINode* aNode1,
|
||||
nsINode* aNode2);
|
||||
static nsINode* GetCommonAncestor(nsINode* aNode1, nsINode* aNode2);
|
||||
|
||||
/**
|
||||
* Returns the common flattened tree ancestor, if any, for two given content
|
||||
* nodes.
|
||||
*/
|
||||
static nsIContent* GetCommonFlattenedTreeAncestor(nsIContent* aContent1,
|
||||
nsIContent* aContent2);
|
||||
|
||||
/**
|
||||
* Returns the common ancestor under interactive content, if any.
|
||||
* If neither one has interactive content as ancestor, common ancestor will be
|
||||
|
|
|
|||
|
|
@ -11910,6 +11910,7 @@ nsIDocument::InlineScriptAllowedByCSP()
|
|||
true, // aParserCreated
|
||||
EmptyString(), // FIXME get script sample (bug 1314567)
|
||||
0, // aLineNumber
|
||||
0, // aColumnNumber
|
||||
&allowsInlineScript);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -538,10 +538,8 @@ nsFocusManager::MoveFocus(mozIDOMWindowProxy* aWindow, nsIDOMElement* aStartElem
|
|||
NS_ENSURE_TRUE(startContent, NS_ERROR_INVALID_ARG);
|
||||
|
||||
window = GetCurrentWindow(startContent);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
window = aWindow ? nsPIDOMWindowOuter::From(aWindow) : mFocusedWindow.get();
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
||||
|
|
@ -867,7 +865,7 @@ nsFocusManager::ContentRemoved(nsIDocument* aDocument, nsIContent* aContent)
|
|||
}
|
||||
}
|
||||
|
||||
NotifyFocusStateChange(content, shouldShowFocusRing, false);
|
||||
NotifyFocusStateChange(content, nullptr, shouldShowFocusRing, false);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
@ -973,6 +971,7 @@ nsFocusManager::WindowHidden(mozIDOMWindowProxy* aWindow)
|
|||
|
||||
if (oldFocusedContent && oldFocusedContent->IsInComposedDoc()) {
|
||||
NotifyFocusStateChange(oldFocusedContent,
|
||||
nullptr,
|
||||
mFocusedWindow->ShouldShowFocusRing(),
|
||||
false);
|
||||
window->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
|
||||
|
|
@ -1091,12 +1090,21 @@ nsFocusManager::ParentActivated(mozIDOMWindowProxy* aWindow, bool aActive)
|
|||
/* static */
|
||||
void
|
||||
nsFocusManager::NotifyFocusStateChange(nsIContent* aContent,
|
||||
nsIContent* aContentToFocus,
|
||||
bool aWindowShouldShowFocusRing,
|
||||
bool aGettingFocus)
|
||||
{
|
||||
MOZ_ASSERT_IF(aContentToFocus, !aGettingFocus);
|
||||
if (!aContent->IsElement()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIContent* commonAncestor = nullptr;
|
||||
if (aContentToFocus && aContentToFocus->IsElement()) {
|
||||
commonAncestor =
|
||||
nsContentUtils::GetCommonFlattenedTreeAncestor(aContent, aContentToFocus);
|
||||
}
|
||||
|
||||
EventStates eventState = NS_EVENT_STATE_FOCUS;
|
||||
if (aWindowShouldShowFocusRing) {
|
||||
eventState |= NS_EVENT_STATE_FOCUSRING;
|
||||
|
|
@ -1108,9 +1116,18 @@ nsFocusManager::NotifyFocusStateChange(nsIContent* aContent,
|
|||
aContent->AsElement()->RemoveStates(eventState);
|
||||
}
|
||||
|
||||
for (Element* element = aContent->AsElement(); element;
|
||||
element = element->GetParentElementCrossingShadowRoot()) {
|
||||
for (nsIContent* content = aContent;
|
||||
content && content != commonAncestor;
|
||||
content = content->GetFlattenedTreeParent()) {
|
||||
if (!content->IsElement()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Element* element = content->AsElement();
|
||||
if (aGettingFocus) {
|
||||
if (element->State().HasState(NS_EVENT_STATE_FOCUS_WITHIN)) {
|
||||
break;
|
||||
}
|
||||
element->AddStates(NS_EVENT_STATE_FOCUS_WITHIN);
|
||||
} else {
|
||||
element->RemoveStates(NS_EVENT_STATE_FOCUS_WITHIN);
|
||||
|
|
@ -1673,7 +1690,10 @@ nsFocusManager::Blur(nsPIDOMWindowOuter* aWindowToClear,
|
|||
content && content->IsInComposedDoc() && !IsNonFocusableRoot(content);
|
||||
if (content) {
|
||||
if (sendBlurEvent) {
|
||||
NotifyFocusStateChange(content, shouldShowFocusRing, false);
|
||||
NotifyFocusStateChange(content,
|
||||
aContentToFocus,
|
||||
shouldShowFocusRing,
|
||||
false);
|
||||
}
|
||||
|
||||
// if an object/plug-in/remote browser is being blurred, move the system focus
|
||||
|
|
@ -1921,7 +1941,10 @@ nsFocusManager::Focus(nsPIDOMWindowOuter* aWindow,
|
|||
if (aFocusChanged)
|
||||
ScrollIntoView(presShell, aContent, aFlags);
|
||||
|
||||
NotifyFocusStateChange(aContent, aWindow->ShouldShowFocusRing(), true);
|
||||
NotifyFocusStateChange(aContent,
|
||||
nullptr,
|
||||
aWindow->ShouldShowFocusRing(),
|
||||
true);
|
||||
|
||||
// if this is an object/plug-in/remote browser, focus its widget. Note that we might
|
||||
// no longer be in the same document, due to the events we fired above when
|
||||
|
|
|
|||
|
|
@ -583,6 +583,7 @@ private:
|
|||
// focus rings: in the losing focus case that information could be
|
||||
// wrong..
|
||||
static void NotifyFocusStateChange(nsIContent* aContent,
|
||||
nsIContent* aContentToFocus,
|
||||
bool aWindowShouldShowFocusRing,
|
||||
bool aGettingFocus);
|
||||
|
||||
|
|
|
|||
|
|
@ -333,6 +333,14 @@ interface nsIContentPolicyBase : nsISupports
|
|||
*/
|
||||
const nsContentPolicyType TYPE_SAVEAS_DOWNLOAD = 42;
|
||||
|
||||
/**
|
||||
* Indicates an importScripts() inside a worker script.
|
||||
*
|
||||
* This will be mapped to TYPE_SCRIPT before being passed to content policy
|
||||
* implementations.
|
||||
*/
|
||||
const nsContentPolicyType TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS = 43;
|
||||
|
||||
/* When adding new content types, please update nsContentBlocker,
|
||||
* NS_CP_ContentTypeName, nsCSPContext, CSP_ContentTypeToDirective,
|
||||
* DoContentSecurityChecks, all nsIContentPolicy implementations, the
|
||||
|
|
|
|||
|
|
@ -101,6 +101,19 @@ public:
|
|||
* was set
|
||||
*/
|
||||
virtual uint32_t GetLineNumber() = 0;
|
||||
|
||||
// This doesn't entirely belong here since they only make sense for
|
||||
// some types of linking elements, but it's a better place than
|
||||
// anywhere else.
|
||||
virtual void SetColumnNumber(uint32_t aColumnNumber) = 0;
|
||||
|
||||
/**
|
||||
* Get the column number, as previously set by SetColumnNumber.
|
||||
*
|
||||
* @return the column number of this element; or 1 if no column number
|
||||
* was set
|
||||
*/
|
||||
virtual uint32_t GetColumnNumber() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIStyleSheetLinkingElement,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/Function.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/dom/CSPEvalChecker.h"
|
||||
#include "mozilla/dom/FunctionBinding.h"
|
||||
#include "mozilla/dom/ModuleScript.h"
|
||||
#include "nsAXPCNativeCallContext.h"
|
||||
|
|
@ -52,7 +53,8 @@ public:
|
|||
Function& aFunction,
|
||||
nsTArray<JS::Heap<JS::Value>>&& aArguments);
|
||||
nsJSScriptTimeoutHandler(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
const nsAString& aExpression);
|
||||
const nsAString& aExpression, bool* aAllowEval,
|
||||
ErrorResult& aRv);
|
||||
|
||||
virtual const nsAString& GetHandlerText() override;
|
||||
|
||||
|
|
@ -182,54 +184,6 @@ NS_INTERFACE_MAP_END
|
|||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsJSScriptTimeoutHandler)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsJSScriptTimeoutHandler)
|
||||
|
||||
static bool
|
||||
CheckCSPForEval(JSContext* aCx, nsGlobalWindow* aWindow, ErrorResult& aError)
|
||||
{
|
||||
// if CSP is enabled, and setTimeout/setInterval was called with a string,
|
||||
// disable the registration and log an error
|
||||
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
|
||||
if (!doc) {
|
||||
// if there's no document, we don't have to do anything.
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
aError = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
if (aError.Failed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!csp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool allowsEval = true;
|
||||
bool reportViolation = false;
|
||||
aError = csp->GetAllowsEval(&reportViolation, &allowsEval);
|
||||
if (aError.Failed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (reportViolation) {
|
||||
// TODO : need actual script sample in violation report.
|
||||
NS_NAMED_LITERAL_STRING(scriptSample,
|
||||
"call to eval() or related function blocked by CSP");
|
||||
|
||||
// Get the calling location.
|
||||
uint32_t lineNum = 0;
|
||||
nsAutoString fileNameString;
|
||||
if (!nsJSUtils::GetCallingLocation(aCx, fileNameString, &lineNum)) {
|
||||
fileNameString.AssignLiteral("unknown");
|
||||
}
|
||||
|
||||
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
|
||||
fileNameString, scriptSample, lineNum,
|
||||
EmptyString(), EmptyString());
|
||||
}
|
||||
|
||||
return allowsEval;
|
||||
}
|
||||
|
||||
nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler()
|
||||
: mLineNo(0)
|
||||
, mColumn(0)
|
||||
|
|
@ -273,8 +227,9 @@ nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler(JSContext* aCx,
|
|||
return;
|
||||
}
|
||||
|
||||
*aAllowEval = CheckCSPForEval(aCx, aWindow, aError);
|
||||
if (aError.Failed() || !*aAllowEval) {
|
||||
aError = CSPEvalChecker::CheckForWindow(aCx, aWindow, aExpression,
|
||||
aAllowEval);
|
||||
if (NS_WARN_IF(aError.Failed()) || !*aAllowEval) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -297,7 +252,9 @@ nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler(JSContext* aCx,
|
|||
|
||||
nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler(JSContext* aCx,
|
||||
WorkerPrivate* aWorkerPrivate,
|
||||
const nsAString& aExpression)
|
||||
const nsAString& aExpression,
|
||||
bool* aAllowEval,
|
||||
ErrorResult& aError)
|
||||
: mLineNo(0)
|
||||
, mColumn(0)
|
||||
, mExpr(aExpression)
|
||||
|
|
@ -305,6 +262,12 @@ nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler(JSContext* aCx,
|
|||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
aError = CSPEvalChecker::CheckForWorker(aCx, aWorkerPrivate, aExpression,
|
||||
aAllowEval);
|
||||
if (NS_WARN_IF(aError.Failed()) || !*aAllowEval) {
|
||||
return;
|
||||
}
|
||||
|
||||
Init(aCx);
|
||||
}
|
||||
|
||||
|
|
@ -399,9 +362,15 @@ NS_CreateJSTimeoutHandler(JSContext *aCx, WorkerPrivate* aWorkerPrivate,
|
|||
|
||||
already_AddRefed<nsIScriptTimeoutHandler>
|
||||
NS_CreateJSTimeoutHandler(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
const nsAString& aExpression)
|
||||
const nsAString& aExpression, ErrorResult& aRv)
|
||||
{
|
||||
bool allowEval = false;
|
||||
RefPtr<nsJSScriptTimeoutHandler> handler =
|
||||
new nsJSScriptTimeoutHandler(aCx, aWorkerPrivate, aExpression);
|
||||
new nsJSScriptTimeoutHandler(aCx, aWorkerPrivate, aExpression, &allowEval,
|
||||
aRv);
|
||||
if (aRv.Failed() || !allowEval) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return handler.forget();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ nsStyleLinkElement::nsStyleLinkElement()
|
|||
: mDontLoadStyle(false)
|
||||
, mUpdatesEnabled(true)
|
||||
, mLineNumber(1)
|
||||
, mColumnNumber(1)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -127,6 +128,18 @@ nsStyleLinkElement::GetLineNumber()
|
|||
return mLineNumber;
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsStyleLinkElement::SetColumnNumber(uint32_t aColumnNumber)
|
||||
{
|
||||
mColumnNumber = aColumnNumber;
|
||||
}
|
||||
|
||||
/* virtual */ uint32_t
|
||||
nsStyleLinkElement::GetColumnNumber()
|
||||
{
|
||||
return mColumnNumber;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsStyleLinkElement::IsImportEnabled()
|
||||
{
|
||||
|
|
@ -412,8 +425,10 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
|
|||
if (!nsStyleUtil::CSPAllowsInlineStyle(thisContent,
|
||||
thisContent->NodePrincipal(),
|
||||
doc->GetDocumentURI(),
|
||||
mLineNumber, text, &rv))
|
||||
mLineNumber, mColumnNumber, text,
|
||||
&rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Parse the style sheet.
|
||||
rv = doc->CSSLoader()->
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ public:
|
|||
virtual void OverrideBaseURI(nsIURI* aNewBaseURI) override;
|
||||
virtual void SetLineNumber(uint32_t aLineNumber) override;
|
||||
virtual uint32_t GetLineNumber() override;
|
||||
void SetColumnNumber(uint32_t aColumnNumber) override;
|
||||
uint32_t GetColumnNumber() override;
|
||||
|
||||
enum RelValue {
|
||||
ePREFETCH = 0x00000001,
|
||||
|
|
@ -140,6 +142,7 @@ protected:
|
|||
bool mDontLoadStyle;
|
||||
bool mUpdatesEnabled;
|
||||
uint32_t mLineNumber;
|
||||
uint32_t mColumnNumber;
|
||||
};
|
||||
|
||||
#endif /* nsStyleLinkElement_h___ */
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ nsStyledElement::ParseStyleAttribute(const nsAString& aValue,
|
|||
|
||||
if (!isNativeAnon &&
|
||||
!nsStyleUtil::CSPAllowsInlineStyle(nullptr, NodePrincipal(),
|
||||
doc->GetDocumentURI(), 0, aValue,
|
||||
doc->GetDocumentURI(), 0, 0, aValue,
|
||||
nullptr))
|
||||
return;
|
||||
|
||||
|
|
|
|||
18
dom/cache/DBSchema.cpp
vendored
18
dom/cache/DBSchema.cpp
vendored
|
|
@ -34,7 +34,7 @@ namespace db {
|
|||
const int32_t kFirstShippedSchemaVersion = 15;
|
||||
namespace {
|
||||
// Update this whenever the DB schema is changed.
|
||||
const int32_t kLatestSchemaVersion = 24;
|
||||
const int32_t kLatestSchemaVersion = 25;
|
||||
// ---------
|
||||
// The following constants define the SQL schema. These are defined in the
|
||||
// same order the SQL should be executed in CreateOrMigrateSchema(). They are
|
||||
|
|
@ -287,7 +287,8 @@ static_assert(nsIContentPolicy::TYPE_INVALID == 0 &&
|
|||
nsIContentPolicy::TYPE_INTERNAL_STYLESHEET == 39 &&
|
||||
nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD == 40 &&
|
||||
nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON == 41 &&
|
||||
nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD == 42,
|
||||
nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD == 42 &&
|
||||
nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS == 43,
|
||||
"nsContentPolicyType values are as expected");
|
||||
|
||||
namespace {
|
||||
|
|
@ -2478,6 +2479,7 @@ nsresult MigrateFrom20To21(mozIStorageConnection* aConn, bool& aRewriteSchema);
|
|||
nsresult MigrateFrom21To22(mozIStorageConnection* aConn, bool& aRewriteSchema);
|
||||
nsresult MigrateFrom22To23(mozIStorageConnection* aConn, bool& aRewriteSchema);
|
||||
nsresult MigrateFrom23To24(mozIStorageConnection* aConn, bool& aRewriteSchema);
|
||||
nsresult MigrateFrom24To25(mozIStorageConnection* aConn, bool& aRewriteSchema);
|
||||
// Configure migration functions to run for the given starting version.
|
||||
Migration sMigrationList[] = {
|
||||
Migration(15, MigrateFrom15To16),
|
||||
|
|
@ -2489,6 +2491,7 @@ Migration sMigrationList[] = {
|
|||
Migration(21, MigrateFrom21To22),
|
||||
Migration(22, MigrateFrom22To23),
|
||||
Migration(23, MigrateFrom23To24),
|
||||
Migration(24, MigrateFrom24To25),
|
||||
};
|
||||
uint32_t sMigrationListLength = sizeof(sMigrationList) / sizeof(Migration);
|
||||
nsresult
|
||||
|
|
@ -3013,6 +3016,17 @@ nsresult MigrateFrom23To24(mozIStorageConnection* aConn, bool& aRewriteSchema)
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult MigrateFrom24To25(mozIStorageConnection* aConn, bool& aRewriteSchema)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_DIAGNOSTIC_ASSERT(aConn);
|
||||
|
||||
// The only change between 24 and 25 was a new nsIContentPolicy type.
|
||||
nsresult rv = aConn->SetSchemaVersion(25);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace db
|
||||
} // namespace cache
|
||||
|
|
|
|||
|
|
@ -598,7 +598,7 @@ private:
|
|||
innerID = NS_LITERAL_STRING("ServiceWorker");
|
||||
// Use scope as ID so the webconsole can decide if the message should
|
||||
// show up per tab
|
||||
id.AssignWithConversion(mWorkerPrivate->WorkerName());
|
||||
id.AssignWithConversion(mWorkerPrivate->ServiceWorkerScope());
|
||||
} else {
|
||||
innerID = NS_LITERAL_STRING("Worker");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -787,28 +787,22 @@ EventListenerManager::SetEventHandler(nsIAtom* aName,
|
|||
rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (csp) {
|
||||
// let's generate a script sample and pass it as aContent,
|
||||
// it will not match the hash, but allows us to pass
|
||||
// the script sample in aContent.
|
||||
nsAutoString scriptSample, attr, tagName(NS_LITERAL_STRING("UNKNOWN"));
|
||||
aName->ToString(attr);
|
||||
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mTarget));
|
||||
if (domNode) {
|
||||
domNode->GetNodeName(tagName);
|
||||
}
|
||||
// build a "script sample" based on what we know about this element
|
||||
scriptSample.Assign(attr);
|
||||
scriptSample.AppendLiteral(" attribute on ");
|
||||
scriptSample.Append(tagName);
|
||||
scriptSample.AppendLiteral(" element");
|
||||
unsigned lineNum = 0;
|
||||
unsigned columnNum = 0;
|
||||
|
||||
JSContext* cx = nsContentUtils::GetCurrentJSContext();
|
||||
if (cx && !JS::DescribeScriptedCaller(cx, nullptr, &lineNum, &columnNum)) {
|
||||
JS_ClearPendingException(cx);
|
||||
}
|
||||
|
||||
if (csp) {
|
||||
bool allowsInlineScript = true;
|
||||
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT,
|
||||
EmptyString(), // aNonce
|
||||
true, // aParserCreated (true because attribute event handler)
|
||||
scriptSample,
|
||||
0, // aLineNumber
|
||||
aBody,
|
||||
lineNum, // aLineNumber
|
||||
columnNum, // aColumnNumber
|
||||
&allowsInlineScript);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
|
|
|||
|
|
@ -4849,48 +4849,13 @@ GetLabelTarget(nsIContent* aPossibleLabel)
|
|||
return label->GetLabeledElement();
|
||||
}
|
||||
|
||||
static nsIContent* FindCommonAncestor(nsIContent *aNode1, nsIContent *aNode2)
|
||||
static nsIContent*
|
||||
FindCommonAncestor(nsIContent *aNode1, nsIContent *aNode2)
|
||||
{
|
||||
// Find closest common ancestor
|
||||
if (aNode1 && aNode2) {
|
||||
// Find the nearest common ancestor by counting the distance to the
|
||||
// root and then walking up again, in pairs.
|
||||
int32_t offset = 0;
|
||||
nsIContent *anc1 = aNode1;
|
||||
for (;;) {
|
||||
++offset;
|
||||
nsIContent* parent = anc1->GetFlattenedTreeParent();
|
||||
if (!parent)
|
||||
break;
|
||||
anc1 = parent;
|
||||
}
|
||||
nsIContent *anc2 = aNode2;
|
||||
for (;;) {
|
||||
--offset;
|
||||
nsIContent* parent = anc2->GetFlattenedTreeParent();
|
||||
if (!parent)
|
||||
break;
|
||||
anc2 = parent;
|
||||
}
|
||||
if (anc1 == anc2) {
|
||||
anc1 = aNode1;
|
||||
anc2 = aNode2;
|
||||
while (offset > 0) {
|
||||
anc1 = anc1->GetFlattenedTreeParent();
|
||||
--offset;
|
||||
}
|
||||
while (offset < 0) {
|
||||
anc2 = anc2->GetFlattenedTreeParent();
|
||||
++offset;
|
||||
}
|
||||
while (anc1 != anc2) {
|
||||
anc1 = anc1->GetFlattenedTreeParent();
|
||||
anc2 = anc2->GetFlattenedTreeParent();
|
||||
}
|
||||
return anc1;
|
||||
}
|
||||
if (!aNode1 || !aNode2) {
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
return nsContentUtils::GetCommonFlattenedTreeAncestor(aNode1, aNode2);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
|||
|
|
@ -710,7 +710,7 @@ WorkerFetchResolver::FlushConsoleReport()
|
|||
return;
|
||||
}
|
||||
|
||||
swm->FlushReportsToAllClients(worker->WorkerName(), mReporter);
|
||||
swm->FlushReportsToAllClients(worker->ServiceWorkerScope(), mReporter);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#include "nsIOutputStream.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIHttpHeaderVisitor.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIThreadRetargetableRequest.h"
|
||||
#include "nsIUploadChannel2.h"
|
||||
|
|
@ -449,38 +448,6 @@ FetchDriver::FailWithNetworkError()
|
|||
mChannel = nullptr;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class FillResponseHeaders final : public nsIHttpHeaderVisitor {
|
||||
InternalResponse* mResponse;
|
||||
|
||||
~FillResponseHeaders()
|
||||
{ }
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
explicit FillResponseHeaders(InternalResponse* aResponse)
|
||||
: mResponse(aResponse)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
VisitHeader(const nsACString & aHeader, const nsACString & aValue) override
|
||||
{
|
||||
ErrorResult result;
|
||||
mResponse->Headers()->Append(aHeader, aValue, result);
|
||||
if (result.Failed()) {
|
||||
NS_WARNING(nsPrintfCString("Fetch ignoring illegal header - '%s': '%s'",
|
||||
PromiseFlatCString(aHeader).get(),
|
||||
PromiseFlatCString(aValue).get()).get());
|
||||
result.SuppressException();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(FillResponseHeaders, nsIHttpHeaderVisitor)
|
||||
} // namespace
|
||||
|
||||
NS_IMETHODIMP
|
||||
FetchDriver::OnStartRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext)
|
||||
|
|
@ -540,11 +507,7 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
|
|||
response = new InternalResponse(responseStatus, statusText,
|
||||
mRequest->GetCredentialsMode());
|
||||
|
||||
RefPtr<FillResponseHeaders> visitor = new FillResponseHeaders(response);
|
||||
rv = httpChannel->VisitResponseHeaders(visitor);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
NS_WARNING("Failed to visit all headers.");
|
||||
}
|
||||
response->Headers()->FillResponseHeaders(httpChannel);
|
||||
|
||||
// If Content-Encoding or Transfer-Encoding headers are set, then the actual
|
||||
// Content-Length (which refer to the decoded data) is obscured behind the encodings.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIHttpHeaderVisitor.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsReadableUtils.h"
|
||||
|
||||
|
|
@ -478,6 +479,48 @@ InternalHeaders::Fill(const Record<nsCString, nsCString>& aInit, ErrorResult& aR
|
|||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class FillHeaders final : public nsIHttpHeaderVisitor
|
||||
{
|
||||
RefPtr<InternalHeaders> mInternalHeaders;
|
||||
|
||||
~FillHeaders() = default;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
explicit FillHeaders(InternalHeaders* aInternalHeaders)
|
||||
: mInternalHeaders(aInternalHeaders)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mInternalHeaders);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
VisitHeader(const nsACString& aHeader, const nsACString& aValue) override
|
||||
{
|
||||
IgnoredErrorResult result;
|
||||
mInternalHeaders->Append(aHeader, aValue, result);
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(FillHeaders, nsIHttpHeaderVisitor)
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
InternalHeaders::FillResponseHeaders(nsIRequest* aRequest)
|
||||
{
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
|
||||
if (!httpChannel) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<FillHeaders> visitor = new FillHeaders(this);
|
||||
httpChannel->VisitResponseHeaders(visitor);
|
||||
}
|
||||
|
||||
bool
|
||||
InternalHeaders::HasOnlySimpleHeaders() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ public:
|
|||
void Fill(const InternalHeaders& aInit, ErrorResult& aRv);
|
||||
void Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& aRv);
|
||||
void Fill(const Record<nsCString, nsCString>& aInit, ErrorResult& aRv);
|
||||
void FillResponseHeaders(nsIRequest* aRequest);
|
||||
|
||||
bool HasOnlySimpleHeaders() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -234,6 +234,7 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte
|
|||
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS:
|
||||
context = RequestContext::Script;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_INTERNAL_WORKER:
|
||||
|
|
|
|||
|
|
@ -6,11 +6,9 @@
|
|||
#include "nsIContentPolicy.idl"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsIChannel;
|
||||
interface nsIDocShell;
|
||||
interface nsIDOMDocument;
|
||||
interface nsIPrincipal;
|
||||
interface nsIURI;
|
||||
|
||||
/**
|
||||
* nsIContentSecurityPolicy
|
||||
|
|
@ -142,6 +140,8 @@ interface nsIContentSecurityPolicy : nsISerializable
|
|||
* (and compare to the hashes listed in the policy)
|
||||
* @param aLineNumber The line number of the inline resource
|
||||
* (used for reporting)
|
||||
* @param aColumnNumber The column number of the inline resource
|
||||
* (used for reporting)
|
||||
* @return
|
||||
* Whether or not the effects of the inline style should be allowed
|
||||
* (block the rules if false).
|
||||
|
|
@ -150,7 +150,8 @@ interface nsIContentSecurityPolicy : nsISerializable
|
|||
in AString aNonce,
|
||||
in boolean aParserCreated,
|
||||
in AString aContent,
|
||||
in unsigned long aLineNumber);
|
||||
in unsigned long aLineNumber,
|
||||
in unsigned long aColumnNumber);
|
||||
|
||||
/**
|
||||
* whether this policy allows eval and eval-like functions
|
||||
|
|
@ -190,6 +191,8 @@ interface nsIContentSecurityPolicy : nsISerializable
|
|||
* sample of the violating content (to aid debugging)
|
||||
* @param lineNum
|
||||
* source line number of the violation (if available)
|
||||
* @param columnNum
|
||||
* source column number of the violation (if available)
|
||||
* @param aNonce
|
||||
* (optional) If this is a nonce violation, include the nonce so we can
|
||||
* recheck to determine which policies were violated and send the
|
||||
|
|
@ -204,6 +207,7 @@ interface nsIContentSecurityPolicy : nsISerializable
|
|||
in AString sourceFile,
|
||||
in AString scriptSample,
|
||||
in int32_t lineNum,
|
||||
in int32_t columnNum,
|
||||
[optional] in AString nonce,
|
||||
[optional] in AString content);
|
||||
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
|
|||
true, // aParserCreated
|
||||
EmptyString(), // aContent
|
||||
0, // aLineNumber
|
||||
0, // aColumnNumber
|
||||
&allowsInlineScript);
|
||||
|
||||
//return early if inline scripts are not allowed
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ ServiceWorkerScopePathMismatch=Failed to register a ServiceWorker: The path of t
|
|||
# LOCALIZATION NOTE: Do not translate "ServiceWorker". %1$S is a URL representing the scope of the ServiceWorker, %2$S is a stringified numeric HTTP status code like "404" and %3$S is a URL.
|
||||
ServiceWorkerRegisterNetworkError=Failed to register/update a ServiceWorker for scope ‘%1$S’: Load failed with status %2$S for script ‘%3$S’.
|
||||
# LOCALIZATION NOTE: Do not translate "ServiceWorker". %1$S is a URL representing the scope of the ServiceWorker, %2$S is a MIME Media Type like "text/plain" and %3$S is a URL.
|
||||
ServiceWorkerRegisterMimeTypeError=Failed to register/update a ServiceWorker for scope ‘%1$S’: Bad Content-Type of ‘%2$S’ received for script ‘%3$S’. Must be ‘text/javascript’, ‘application/x-javascript’, or ‘application/javascript’.
|
||||
ServiceWorkerRegisterMimeTypeError2=Failed to register/update a ServiceWorker for scope ‘%1$S’: Bad Content-Type of ‘%2$S’ received for script ‘%3$S’. Must be ‘text/javascript’, ‘application/x-javascript’, or ‘application/javascript’.
|
||||
# LOCALIZATION NOTE: Do not translate "ServiceWorker". %1$S is a URL representing the scope of the ServiceWorker.
|
||||
ServiceWorkerGraceTimeoutTermination=Terminating ServiceWorker for scope ‘%1$S’ with pending waitUntil/respondWith promises because of grace timeout.
|
||||
ExecCommandCutCopyDeniedNotInputDriven=document.execCommand(‘cut’/‘copy’) was denied because it was not called from inside a short running user-generated event handler.
|
||||
|
|
|
|||
|
|
@ -112,10 +112,6 @@ couldntParsePort = Couldn’t parse port in %1$S
|
|||
# LOCALIZATION NOTE (duplicateDirective):
|
||||
# %1$S is the name of the duplicate directive
|
||||
duplicateDirective = Duplicate %1$S directives detected. All but the first instance will be ignored.
|
||||
# LOCALIZATION NOTE (deprecatedChildSrcDirective):
|
||||
# %1$S is the value of the deprecated directive.
|
||||
# Do not localize: worker-src, frame-src
|
||||
deprecatedChildSrcDirective = Directive ‘%1$S’ has been deprecated. Please use directive ‘worker-src’ to control workers, or directive ‘frame-src’ to control frames respectively.
|
||||
# LOCALIZATION NOTE (couldntParseInvalidSandboxFlag):
|
||||
# %1$S is the option that could not be understood
|
||||
couldntParseInvalidSandboxFlag = Couldn’t parse invalid sandbox flag ‘%1$S’
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ MimeTypeMismatch=The resource from “%1$S” was blocked due to MIME type misma
|
|||
XCTOHeaderValueMissing=X-Content-Type-Options header warning: value was “%1$S”; did you mean to send “nosniff”?
|
||||
|
||||
BlockScriptWithWrongMimeType=Script from “%1$S” was blocked because of a disallowed MIME type.
|
||||
# LOCALIZATION NOTE: Do not translate "importScripts()"
|
||||
BlockImportScriptsWithWrongMimeType=Loading script from “%1$S” with importScripts() was blocked because of a disallowed MIME type.
|
||||
|
||||
# LOCALIZATION NOTE: Do not translate "data: URI".
|
||||
BlockTopLevelDataURINavigation=Navigation to toplevel data: URI not allowed (Blocked loading of: “%1$S”)
|
||||
|
|
|
|||
|
|
@ -1474,6 +1474,7 @@ CSPAllowsInlineScript(nsIScriptElement *aElement, nsIDocument *aDocument)
|
|||
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT,
|
||||
nonce, parserCreated, scriptText,
|
||||
aElement->GetScriptLineNumber(),
|
||||
aElement->GetScriptColumnNumber(),
|
||||
&allowInlineScript);
|
||||
return allowInlineScript;
|
||||
}
|
||||
|
|
@ -2695,10 +2696,11 @@ ScriptLoader::VerifySRI(ScriptLoadRequest* aRequest,
|
|||
nsAutoCString violationURISpec;
|
||||
mDocument->GetDocumentURI()->GetAsciiSpec(violationURISpec);
|
||||
uint32_t lineNo = aRequest->Element() ? aRequest->Element()->GetScriptLineNumber() : 0;
|
||||
uint32_t columnNo = aRequest->Element() ? aRequest->Element()->GetScriptColumnNumber() : 0;
|
||||
csp->LogViolationDetails(
|
||||
nsIContentSecurityPolicy::VIOLATION_TYPE_REQUIRE_SRI_FOR_SCRIPT,
|
||||
NS_ConvertUTF8toUTF16(violationURISpec),
|
||||
EmptyString(), lineNo, EmptyString(), EmptyString());
|
||||
EmptyString(), lineNo, columnNo, EmptyString(), EmptyString());
|
||||
rv = NS_ERROR_SRI_CORRUPT;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ public:
|
|||
|
||||
explicit nsIScriptElement(mozilla::dom::FromParser aFromParser)
|
||||
: mLineNumber(1),
|
||||
mColumnNumber(1),
|
||||
mAlreadyStarted(false),
|
||||
mMalformed(false),
|
||||
mDoneAddingChildren(aFromParser == mozilla::dom::NOT_FROM_PARSER ||
|
||||
|
|
@ -138,6 +139,16 @@ public:
|
|||
return mLineNumber;
|
||||
}
|
||||
|
||||
void SetScriptColumnNumber(uint32_t aColumnNumber)
|
||||
{
|
||||
mColumnNumber = aColumnNumber;
|
||||
}
|
||||
|
||||
uint32_t GetScriptColumnNumber()
|
||||
{
|
||||
return mColumnNumber;
|
||||
}
|
||||
|
||||
void SetIsMalformed()
|
||||
{
|
||||
mMalformed = true;
|
||||
|
|
@ -281,6 +292,11 @@ protected:
|
|||
*/
|
||||
uint32_t mLineNumber;
|
||||
|
||||
/**
|
||||
* The start column number of the script.
|
||||
*/
|
||||
uint32_t mColumnNumber;
|
||||
|
||||
/**
|
||||
* The "already started" flag per HTML5.
|
||||
*/
|
||||
|
|
|
|||
183
dom/security/CSPEvalChecker.cpp
Normal file
183
dom/security/CSPEvalChecker.cpp
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/CSPEvalChecker.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
#include "mozilla/dom/WorkerRunnable.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsJSUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
namespace {
|
||||
|
||||
nsresult
|
||||
CheckInternal(nsIContentSecurityPolicy* aCSP,
|
||||
const nsAString& aExpression,
|
||||
const nsAString& aFileNameString,
|
||||
uint32_t aLineNum,
|
||||
uint32_t aColumnNum,
|
||||
bool* aAllowed)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aAllowed);
|
||||
|
||||
// The value is set at any "return", but better to have a default value here.
|
||||
*aAllowed = false;
|
||||
|
||||
if (!aCSP) {
|
||||
*aAllowed = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool reportViolation = false;
|
||||
nsresult rv = aCSP->GetAllowsEval(&reportViolation, aAllowed);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
*aAllowed = false;
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (reportViolation) {
|
||||
aCSP->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
|
||||
aFileNameString, aExpression, aLineNum,
|
||||
aColumnNum, EmptyString(), EmptyString());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class WorkerCSPCheckRunnable final : public WorkerMainThreadRunnable
|
||||
{
|
||||
public:
|
||||
WorkerCSPCheckRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsAString& aExpression,
|
||||
const nsAString& aFileNameString,
|
||||
uint32_t aLineNum,
|
||||
uint32_t aColumnNum)
|
||||
: WorkerMainThreadRunnable(aWorkerPrivate,
|
||||
NS_LITERAL_CSTRING("CSP Eval Check"))
|
||||
, mExpression(aExpression)
|
||||
, mFileNameString(aFileNameString)
|
||||
, mLineNum(aLineNum)
|
||||
, mColumnNum(aColumnNum)
|
||||
, mEvalAllowed(false)
|
||||
{}
|
||||
|
||||
bool
|
||||
MainThreadRun() override
|
||||
{
|
||||
mResult = CheckInternal(mWorkerPrivate->GetCSP(), mExpression,
|
||||
mFileNameString, mLineNum, mColumnNum,
|
||||
&mEvalAllowed);
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GetResult(bool* aAllowed)
|
||||
{
|
||||
MOZ_ASSERT(aAllowed);
|
||||
*aAllowed = mEvalAllowed;
|
||||
return mResult;
|
||||
}
|
||||
|
||||
private:
|
||||
const nsString mExpression;
|
||||
const nsString mFileNameString;
|
||||
const uint32_t mLineNum;
|
||||
const uint32_t mColumnNum;
|
||||
bool mEvalAllowed;
|
||||
nsresult mResult;
|
||||
};
|
||||
|
||||
} // anonymous
|
||||
|
||||
/* static */ nsresult
|
||||
CSPEvalChecker::CheckForWindow(JSContext* aCx, nsGlobalWindow* aWindow,
|
||||
const nsAString& aExpression, bool* aAllowEval)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aAllowEval);
|
||||
|
||||
// The value is set at any "return", but better to have a default value here.
|
||||
*aAllowEval = false;
|
||||
|
||||
// if CSP is enabled, and setTimeout/setInterval was called with a string,
|
||||
// disable the registration and log an error
|
||||
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
|
||||
if (!doc) {
|
||||
// if there's no document, we don't have to do anything.
|
||||
*aAllowEval = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
nsresult rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
*aAllowEval = false;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Get the calling location.
|
||||
uint32_t lineNum = 0;
|
||||
uint32_t columnNum = 0;
|
||||
nsAutoString fileNameString;
|
||||
if (!nsJSUtils::GetCallingLocation(aCx, fileNameString, &lineNum,
|
||||
&columnNum)) {
|
||||
fileNameString.AssignLiteral("unknown");
|
||||
}
|
||||
|
||||
rv = CheckInternal(csp, aExpression, fileNameString, lineNum, columnNum,
|
||||
aAllowEval);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
*aAllowEval = false;
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
CSPEvalChecker::CheckForWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
const nsAString& aExpression, bool* aAllowEval)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
MOZ_ASSERT(aAllowEval);
|
||||
|
||||
// The value is set at any "return", but better to have a default value here.
|
||||
*aAllowEval = false;
|
||||
|
||||
// Get the calling location.
|
||||
uint32_t lineNum = 0;
|
||||
uint32_t columnNum = 0;
|
||||
nsAutoString fileNameString;
|
||||
if (!nsJSUtils::GetCallingLocation(aCx, fileNameString, &lineNum,
|
||||
&columnNum)) {
|
||||
fileNameString.AssignLiteral("unknown");
|
||||
}
|
||||
|
||||
RefPtr<WorkerCSPCheckRunnable> r =
|
||||
new WorkerCSPCheckRunnable(aWorkerPrivate, aExpression, fileNameString,
|
||||
lineNum, columnNum);
|
||||
ErrorResult error;
|
||||
r->Dispatch(Canceling, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
*aAllowEval = false;
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
nsresult rv = r->GetResult(aAllowEval);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
*aAllowEval = false;
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
37
dom/security/CSPEvalChecker.h
Normal file
37
dom/security/CSPEvalChecker.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_CSPEvalChecker_h
|
||||
#define mozilla_dom_CSPEvalChecker_h
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
struct JSContext;
|
||||
class nsGlobalWindow;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace workers {
|
||||
class WorkerPrivate;
|
||||
}
|
||||
|
||||
using namespace mozilla::dom::workers;
|
||||
|
||||
class CSPEvalChecker final
|
||||
{
|
||||
public:
|
||||
static nsresult
|
||||
CheckForWindow(JSContext* aCx, nsGlobalWindow* aWindow,
|
||||
const nsAString& aExpression, bool* aAllowEval);
|
||||
|
||||
static nsresult
|
||||
CheckForWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
const nsAString& aExpression, bool* aAllowEval);
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif // mozilla_dom_CSPEvalChecker_h
|
||||
|
|
@ -7,6 +7,7 @@ TEST_DIRS += ['test']
|
|||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'ContentVerifier.h',
|
||||
'CSPEvalChecker.h',
|
||||
'nsContentSecurityManager.h',
|
||||
'nsCSPContext.h',
|
||||
'nsCSPService.h',
|
||||
|
|
@ -24,6 +25,7 @@ EXPORTS += [
|
|||
|
||||
UNIFIED_SOURCES += [
|
||||
'ContentVerifier.cpp',
|
||||
'CSPEvalChecker.cpp',
|
||||
'nsContentSecurityManager.cpp',
|
||||
'nsCSPContext.cpp',
|
||||
'nsCSPParser.cpp',
|
||||
|
|
@ -39,6 +41,7 @@ include('/ipc/chromium/chromium-config.mozbuild')
|
|||
FINAL_LIBRARY = 'xul'
|
||||
LOCAL_INCLUDES += [
|
||||
'/caps',
|
||||
'/dom/base',
|
||||
'/netwerk/base',
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
|
@ -37,6 +40,7 @@
|
|||
#include "nsScriptSecurityManager.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/CSPReportBinding.h"
|
||||
#include "mozilla/dom/CSPDictionariesBinding.h"
|
||||
#include "mozilla/net/ReferrerPolicy.h"
|
||||
|
|
@ -58,6 +62,29 @@ GetCspContextLog()
|
|||
|
||||
static const uint32_t CSP_CACHE_URI_CUTOFF_SIZE = 512;
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* This function is only used for verification purposes within
|
||||
* GatherSecurityPolicyViolationEventData.
|
||||
*/
|
||||
static bool
|
||||
ValidateDirectiveName(const nsAString& aDirective)
|
||||
{
|
||||
static const auto directives = [] () {
|
||||
std::unordered_set<std::string> directives;
|
||||
constexpr size_t dirLen = sizeof(CSPStrDirectives) / sizeof(CSPStrDirectives[0]);
|
||||
for (size_t i = 0; i < dirLen; ++i) {
|
||||
directives.insert(CSPStrDirectives[i]);
|
||||
}
|
||||
return directives;
|
||||
} ();
|
||||
|
||||
nsAutoString directive(aDirective);
|
||||
auto itr = directives.find(NS_ConvertUTF16toUTF8(directive).get());
|
||||
return itr != directives.end();
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
/**
|
||||
* Creates a key for use in the ShouldLoad cache.
|
||||
* Looks like: <uri>!<nsIContentPolicy::LOAD_TYPE>
|
||||
|
|
@ -237,15 +264,25 @@ nsCSPContext::permitsInternal(CSPDirective aDir,
|
|||
// decision may be wrong due to the inability to get the nonce, and will
|
||||
// incorrectly fail the unit tests.
|
||||
if (!aIsPreload && aSendViolationReports) {
|
||||
uint32_t lineNumber = 0;
|
||||
uint32_t columnNumber = 0;
|
||||
nsAutoCString spec;
|
||||
JSContext* cx = nsContentUtils::GetCurrentJSContext();
|
||||
if (cx) {
|
||||
nsJSUtils::GetCallingLocation(cx, spec, &lineNumber, &columnNumber);
|
||||
// If GetCallingLocation fails linenumber & columnNumber are set to 0
|
||||
// anyway so we can skip checking if that is the case.
|
||||
}
|
||||
this->AsyncReportViolation((aSendContentLocationInViolationReports ?
|
||||
aContentLocation : nullptr),
|
||||
aOriginalURI, /* in case of redirect originalURI is not null */
|
||||
violatedDirective,
|
||||
p, /* policy index */
|
||||
EmptyString(), /* no observer subject */
|
||||
EmptyString(), /* no source file */
|
||||
EmptyString(), /* no script sample */
|
||||
0); /* no line number */
|
||||
aOriginalURI, /* in case of redirect originalURI is not null */
|
||||
violatedDirective,
|
||||
p, /* policy index */
|
||||
EmptyString(), /* no observer subject */
|
||||
NS_ConvertUTF8toUTF16(spec), /* source file. */
|
||||
EmptyString(), /* no script sample */
|
||||
lineNumber, /* line number */
|
||||
columnNumber); /* column number */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -266,12 +303,22 @@ NS_IMPL_ISUPPORTS_CI(nsCSPContext,
|
|||
nsIContentSecurityPolicy,
|
||||
nsISerializable)
|
||||
|
||||
int32_t nsCSPContext::sScriptSampleMaxLength;
|
||||
|
||||
nsCSPContext::nsCSPContext()
|
||||
: mInnerWindowID(0)
|
||||
, mLoadingContext(nullptr)
|
||||
, mLoadingPrincipal(nullptr)
|
||||
, mQueueUpMessages(true)
|
||||
{
|
||||
static bool sInitialized = false;
|
||||
if (!sInitialized) {
|
||||
Preferences::AddIntVarCache(&sScriptSampleMaxLength,
|
||||
"security.csp.reporting.script-sample.max-length",
|
||||
40);
|
||||
sInitialized = true;
|
||||
}
|
||||
|
||||
CSPCONTEXTLOG(("nsCSPContext::nsCSPContext"));
|
||||
}
|
||||
|
||||
|
|
@ -444,7 +491,8 @@ nsCSPContext::reportInlineViolation(nsContentPolicyType aContentType,
|
|||
const nsAString& aContent,
|
||||
const nsAString& aViolatedDirective,
|
||||
uint32_t aViolatedPolicyIndex, // TODO, use report only flag for that
|
||||
uint32_t aLineNumber)
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber)
|
||||
{
|
||||
nsString observerSubject;
|
||||
// if the nonce is non empty, then we report the nonce error, otherwise
|
||||
|
|
@ -463,7 +511,7 @@ nsCSPContext::reportInlineViolation(nsContentPolicyType aContentType,
|
|||
|
||||
nsCOMPtr<nsISupportsCString> selfICString(do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID));
|
||||
if (selfICString) {
|
||||
selfICString->SetData(nsDependentCString("self"));
|
||||
selfICString->SetData(nsDependentCString("inline"));
|
||||
}
|
||||
nsCOMPtr<nsISupports> selfISupports(do_QueryInterface(selfICString));
|
||||
|
||||
|
|
@ -474,11 +522,27 @@ nsCSPContext::reportInlineViolation(nsContentPolicyType aContentType,
|
|||
}
|
||||
|
||||
nsAutoString codeSample(aContent);
|
||||
// cap the length of the script sample at 40 chars
|
||||
if (codeSample.Length() > 40) {
|
||||
codeSample.Truncate(40);
|
||||
// cap the length of the script sample
|
||||
if (codeSample.Length() > ScriptSampleMaxLength()) {
|
||||
codeSample.Truncate(ScriptSampleMaxLength());
|
||||
codeSample.AppendLiteral("...");
|
||||
}
|
||||
|
||||
uint32_t lineNumber = aLineNumber;
|
||||
uint32_t columnNumber = aColumnNumber;
|
||||
|
||||
JSContext* cx = nsContentUtils::GetCurrentJSContext();
|
||||
if (cx) {
|
||||
if (!nsJSUtils::GetCallingLocation(cx, sourceFile, &lineNumber,
|
||||
&columnNumber)) {
|
||||
// Get Calling Location resets line/col to 0
|
||||
// so we reset those to the intial arguments
|
||||
// in case it failed
|
||||
lineNumber = aLineNumber;
|
||||
columnNumber = aColumnNumber;
|
||||
}
|
||||
}
|
||||
|
||||
AsyncReportViolation(selfISupports, // aBlockedContentSource
|
||||
mSelfURI, // aOriginalURI
|
||||
aViolatedDirective, // aViolatedDirective
|
||||
|
|
@ -486,7 +550,8 @@ nsCSPContext::reportInlineViolation(nsContentPolicyType aContentType,
|
|||
observerSubject, // aObserverSubject
|
||||
NS_ConvertUTF8toUTF16(sourceFile), // aSourceFile
|
||||
codeSample, // aScriptSample
|
||||
aLineNumber); // aLineNum
|
||||
lineNumber, // aLineNum
|
||||
columnNumber); // aColumnNum
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
@ -495,6 +560,7 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
|
|||
bool aParserCreated,
|
||||
const nsAString& aContent,
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber,
|
||||
bool* outAllowsInline)
|
||||
{
|
||||
*outAllowsInline = true;
|
||||
|
|
@ -539,7 +605,8 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
|
|||
aContent,
|
||||
violatedDirective,
|
||||
i,
|
||||
aLineNumber);
|
||||
aLineNumber,
|
||||
aColumnNumber);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
|
|
@ -558,7 +625,8 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
|
|||
* which is why we must check allows() again here.
|
||||
*
|
||||
* Note: This macro uses some parameters from its caller's context:
|
||||
* p, mPolicies, this, aSourceFile, aScriptSample, aLineNum, selfISupports
|
||||
* p, mPolicies, this, aSourceFile, aScriptSample, aLineNum, aColumnNum,
|
||||
* selfISupports
|
||||
*
|
||||
* @param violationType: the VIOLATION_TYPE_* constant (partial symbol)
|
||||
* such as INLINE_SCRIPT
|
||||
|
|
@ -585,8 +653,8 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
|
|||
nsIContentPolicy::TYPE_ ## contentPolicyType, \
|
||||
violatedDirective); \
|
||||
this->AsyncReportViolation(selfISupports, nullptr, violatedDirective, p, \
|
||||
NS_LITERAL_STRING(observerTopic), \
|
||||
aSourceFile, aScriptSample, aLineNum); \
|
||||
NS_LITERAL_STRING(observerTopic), aSourceFile,\
|
||||
aScriptSample, aLineNum, aColumnNum); \
|
||||
} \
|
||||
PR_END_MACRO; \
|
||||
break
|
||||
|
|
@ -618,6 +686,7 @@ nsCSPContext::LogViolationDetails(uint16_t aViolationType,
|
|||
const nsAString& aSourceFile,
|
||||
const nsAString& aScriptSample,
|
||||
int32_t aLineNum,
|
||||
int32_t aColumnNum,
|
||||
const nsAString& aNonce,
|
||||
const nsAString& aContent)
|
||||
{
|
||||
|
|
@ -626,7 +695,16 @@ nsCSPContext::LogViolationDetails(uint16_t aViolationType,
|
|||
|
||||
nsCOMPtr<nsISupportsCString> selfICString(do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID));
|
||||
if (selfICString) {
|
||||
selfICString->SetData(nsDependentCString("self"));
|
||||
if (aViolationType == nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL) {
|
||||
selfICString->SetData(nsDependentCString("eval"));
|
||||
} else if (aViolationType == nsIContentSecurityPolicy::VIOLATION_TYPE_INLINE_SCRIPT ||
|
||||
aViolationType == nsIContentSecurityPolicy::VIOLATION_TYPE_INLINE_STYLE) {
|
||||
selfICString->SetData(nsDependentCString("inline"));
|
||||
} else {
|
||||
// All the other types should have a URL, but just in case, let's use
|
||||
// 'self' here.
|
||||
selfICString->SetData(nsDependentCString("self"));
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsISupports> selfISupports(do_QueryInterface(selfICString));
|
||||
|
||||
|
|
@ -799,34 +877,23 @@ StripURIForReporting(nsIURI* aURI,
|
|||
aURI->GetSpecIgnoringRef(outStrippedURI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends CSP violation reports to all sources listed under report-uri.
|
||||
*
|
||||
* @param aBlockedContentSource
|
||||
* Either a CSP Source (like 'self', as string) or nsIURI: the source
|
||||
* of the violation.
|
||||
* @param aOriginalUri
|
||||
* The original URI if the blocked content is a redirect, else null
|
||||
* @param aViolatedDirective
|
||||
* the directive that was violated (string).
|
||||
* @param aSourceFile
|
||||
* name of the file containing the inline script violation
|
||||
* @param aScriptSample
|
||||
* a sample of the violating inline script
|
||||
* @param aLineNum
|
||||
* source line number of the violation (if available)
|
||||
*/
|
||||
nsresult
|
||||
nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
|
||||
nsIURI* aOriginalURI,
|
||||
nsAString& aViolatedDirective,
|
||||
uint32_t aViolatedPolicyIndex,
|
||||
nsAString& aSourceFile,
|
||||
nsAString& aScriptSample,
|
||||
uint32_t aLineNum)
|
||||
nsCSPContext::GatherSecurityPolicyViolationEventData(
|
||||
nsIURI* aBlockedURI,
|
||||
const nsACString& aBlockedString,
|
||||
nsIURI* aOriginalURI,
|
||||
nsAString& aViolatedDirective,
|
||||
uint32_t aViolatedPolicyIndex,
|
||||
nsAString& aSourceFile,
|
||||
nsAString& aScriptSample,
|
||||
uint32_t aLineNum,
|
||||
uint32_t aColumnNum,
|
||||
mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit)
|
||||
{
|
||||
NS_ENSURE_ARG_MAX(aViolatedPolicyIndex, mPolicies.Length() - 1);
|
||||
|
||||
MOZ_ASSERT(ValidateDirectiveName(aViolatedDirective), "Invalid directive name");
|
||||
|
||||
if (!CSPService::sCSPReportingEnabled) {
|
||||
// Reporting is pref-disabled. Don't do any actual work and return success.
|
||||
nsContentUtils::ReportToConsoleNonLocalized(
|
||||
|
|
@ -837,48 +904,39 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
dom::CSPReport report;
|
||||
nsresult rv;
|
||||
|
||||
// blocked-uri
|
||||
if (aBlockedContentSource) {
|
||||
nsAutoCString reportBlockedURI;
|
||||
nsCOMPtr<nsIURI> uri = do_QueryInterface(aBlockedContentSource);
|
||||
// could be a string or URI
|
||||
if (uri) {
|
||||
StripURIForReporting(uri, mSelfURI, reportBlockedURI);
|
||||
} else {
|
||||
nsCOMPtr<nsISupportsCString> cstr = do_QueryInterface(aBlockedContentSource);
|
||||
if (cstr) {
|
||||
cstr->GetData(reportBlockedURI);
|
||||
}
|
||||
}
|
||||
if (reportBlockedURI.IsEmpty()) {
|
||||
// this can happen for frame-ancestors violation where the violating
|
||||
// ancestor is cross-origin.
|
||||
NS_WARNING("No blocked URI (null aBlockedContentSource) for CSP violation report.");
|
||||
}
|
||||
report.mCsp_report.mBlocked_uri = NS_ConvertUTF8toUTF16(reportBlockedURI);
|
||||
}
|
||||
|
||||
// document-uri
|
||||
nsAutoCString reportDocumentURI;
|
||||
StripURIForReporting(mSelfURI, mSelfURI, reportDocumentURI);
|
||||
report.mCsp_report.mDocument_uri = NS_ConvertUTF8toUTF16(reportDocumentURI);
|
||||
aViolationEventInit.mDocumentURI = NS_ConvertUTF8toUTF16(reportDocumentURI);
|
||||
|
||||
// referrer
|
||||
aViolationEventInit.mReferrer = mReferrer;
|
||||
|
||||
// blocked-uri
|
||||
if (aBlockedURI) {
|
||||
nsAutoCString reportBlockedURI;
|
||||
StripURIForReporting(aBlockedURI, mSelfURI, reportBlockedURI);
|
||||
aViolationEventInit.mBlockedURI = NS_ConvertUTF8toUTF16(reportBlockedURI);
|
||||
} else {
|
||||
aViolationEventInit.mBlockedURI = NS_ConvertUTF8toUTF16(aBlockedString);
|
||||
}
|
||||
|
||||
// effective-directive
|
||||
// The name of the policy directive that was violated.
|
||||
aViolationEventInit.mEffectiveDirective = aViolatedDirective;
|
||||
|
||||
// violated-directive
|
||||
// In CSP2, the policy directive that was violated, as it appears in the policy.
|
||||
// In CSP3, the same as effective-directive.
|
||||
aViolationEventInit.mViolatedDirective = aViolatedDirective;
|
||||
|
||||
// original-policy
|
||||
nsAutoString originalPolicy;
|
||||
rv = this->GetPolicyString(aViolatedPolicyIndex, originalPolicy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
report.mCsp_report.mOriginal_policy = originalPolicy;
|
||||
|
||||
// referrer
|
||||
if (!mReferrer.IsEmpty()) {
|
||||
report.mCsp_report.mReferrer = mReferrer;
|
||||
}
|
||||
|
||||
// violated-directive
|
||||
report.mCsp_report.mViolated_directive = aViolatedDirective;
|
||||
aViolationEventInit.mOriginalPolicy = originalPolicy;
|
||||
|
||||
// source-file
|
||||
if (!aSourceFile.IsEmpty()) {
|
||||
|
|
@ -890,20 +948,102 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
|
|||
sourceURI->GetSpecIgnoringRef(spec);
|
||||
aSourceFile = NS_ConvertUTF8toUTF16(spec);
|
||||
}
|
||||
aViolationEventInit.mSourceFile = aSourceFile;
|
||||
}
|
||||
|
||||
// sample, max 40 chars.
|
||||
aViolationEventInit.mSample = aScriptSample;
|
||||
uint32_t length = aViolationEventInit.mSample.Length();
|
||||
if (length > ScriptSampleMaxLength()) {
|
||||
uint32_t desiredLength = ScriptSampleMaxLength();
|
||||
// Don't cut off right before a low surrogate. Just include it.
|
||||
if (NS_IS_LOW_SURROGATE(aViolationEventInit.mSample[desiredLength])) {
|
||||
desiredLength++;
|
||||
}
|
||||
aViolationEventInit.mSample.Replace(ScriptSampleMaxLength(),
|
||||
length - desiredLength,
|
||||
nsContentUtils::GetLocalizedEllipsis());
|
||||
}
|
||||
|
||||
// disposition
|
||||
aViolationEventInit.mDisposition = mPolicies[aViolatedPolicyIndex]->getReportOnlyFlag()
|
||||
? mozilla::dom::SecurityPolicyViolationEventDisposition::Report
|
||||
: mozilla::dom::SecurityPolicyViolationEventDisposition::Enforce;
|
||||
|
||||
// status-code
|
||||
uint16_t statusCode = 0;
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mLoadingContext);
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIHttpChannel> channel = do_QueryInterface(doc->GetChannel());
|
||||
if (channel) {
|
||||
uint32_t responseStatus = 0;
|
||||
nsresult rv = channel->GetResponseStatus(&responseStatus);
|
||||
if (NS_SUCCEEDED(rv) && (responseStatus <= UINT16_MAX)) {
|
||||
statusCode = static_cast<uint16_t>(responseStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
aViolationEventInit.mStatusCode = statusCode;
|
||||
|
||||
// line-number
|
||||
aViolationEventInit.mLineNumber = aLineNum;
|
||||
|
||||
// column-number
|
||||
aViolationEventInit.mColumnNumber = aColumnNum;
|
||||
|
||||
aViolationEventInit.mBubbles = true;
|
||||
aViolationEventInit.mComposed = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCSPContext::SendReports(
|
||||
const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit,
|
||||
uint32_t aViolatedPolicyIndex)
|
||||
{
|
||||
NS_ENSURE_ARG_MAX(aViolatedPolicyIndex, mPolicies.Length() - 1);
|
||||
|
||||
dom::CSPReport report;
|
||||
|
||||
// blocked-uri
|
||||
report.mCsp_report.mBlocked_uri = aViolationEventInit.mBlockedURI;
|
||||
|
||||
// document-uri
|
||||
report.mCsp_report.mDocument_uri = aViolationEventInit.mDocumentURI;
|
||||
|
||||
// original-policy
|
||||
report.mCsp_report.mOriginal_policy = aViolationEventInit.mOriginalPolicy;
|
||||
|
||||
// referrer
|
||||
report.mCsp_report.mReferrer = aViolationEventInit.mReferrer;
|
||||
|
||||
// violated-directive
|
||||
report.mCsp_report.mViolated_directive = aViolationEventInit.mViolatedDirective;
|
||||
|
||||
// source-file
|
||||
if (!aViolationEventInit.mSourceFile.IsEmpty()) {
|
||||
report.mCsp_report.mSource_file.Construct();
|
||||
report.mCsp_report.mSource_file.Value() = aSourceFile;
|
||||
report.mCsp_report.mSource_file.Value() = aViolationEventInit.mSourceFile;
|
||||
}
|
||||
|
||||
// script-sample
|
||||
if (!aScriptSample.IsEmpty()) {
|
||||
if (!aViolationEventInit.mSample.IsEmpty()) {
|
||||
report.mCsp_report.mScript_sample.Construct();
|
||||
report.mCsp_report.mScript_sample.Value() = aScriptSample;
|
||||
report.mCsp_report.mScript_sample.Value() = aViolationEventInit.mSample;
|
||||
}
|
||||
|
||||
// line-number
|
||||
if (aLineNum != 0) {
|
||||
if (aViolationEventInit.mLineNumber != 0) {
|
||||
report.mCsp_report.mLine_number.Construct();
|
||||
report.mCsp_report.mLine_number.Value() = aLineNum;
|
||||
report.mCsp_report.mLine_number.Value() = aViolationEventInit.mLineNumber;
|
||||
}
|
||||
|
||||
if (aViolationEventInit.mColumnNumber != 0) {
|
||||
report.mCsp_report.mColumn_number.Construct();
|
||||
report.mCsp_report.mColumn_number.Value() = aViolationEventInit.mColumnNumber;
|
||||
}
|
||||
|
||||
nsString csp_report;
|
||||
|
|
@ -916,11 +1056,11 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
|
|||
nsTArray<nsString> reportURIs;
|
||||
mPolicies[aViolatedPolicyIndex]->getReportURIs(reportURIs);
|
||||
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mLoadingContext);
|
||||
nsCOMPtr<nsIURI> reportURI;
|
||||
nsCOMPtr<nsIChannel> reportChannel;
|
||||
|
||||
nsresult rv;
|
||||
for (uint32_t r = 0; r < reportURIs.Length(); r++) {
|
||||
nsAutoCString reportURICstring = NS_ConvertUTF16toUTF8(reportURIs[r]);
|
||||
// try to create a new uri from every report-uri string
|
||||
|
|
@ -930,7 +1070,9 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
|
|||
CSPCONTEXTLOG(("Could not create nsIURI for report URI %s",
|
||||
reportURICstring.get()));
|
||||
logToConsole(u"triedToSendReport", params, ArrayLength(params),
|
||||
aSourceFile, aScriptSample, aLineNum, 0, nsIScriptError::errorFlag);
|
||||
aViolationEventInit.mSourceFile, aViolationEventInit.mSample,
|
||||
aViolationEventInit.mLineNumber, aViolationEventInit.mColumnNumber,
|
||||
nsIScriptError::errorFlag);
|
||||
continue; // don't return yet, there may be more URIs
|
||||
}
|
||||
|
||||
|
|
@ -971,7 +1113,9 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
|
|||
if (!isHttpScheme) {
|
||||
const char16_t* params[] = { reportURIs[r].get() };
|
||||
logToConsole(u"reportURInotHttpsOrHttp2", params, ArrayLength(params),
|
||||
aSourceFile, aScriptSample, aLineNum, 0, nsIScriptError::errorFlag);
|
||||
aViolationEventInit.mSourceFile, aViolationEventInit.mSample,
|
||||
aViolationEventInit.mLineNumber, aViolationEventInit.mColumnNumber,
|
||||
nsIScriptError::errorFlag);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1035,7 +1179,9 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
|
|||
const char16_t* params[] = { reportURIs[r].get() };
|
||||
CSPCONTEXTLOG(("AsyncOpen failed for report URI %s", params[0]));
|
||||
logToConsole(u"triedToSendReport", params, ArrayLength(params),
|
||||
aSourceFile, aScriptSample, aLineNum, 0, nsIScriptError::errorFlag);
|
||||
aViolationEventInit.mSourceFile, aViolationEventInit.mSample,
|
||||
aViolationEventInit.mLineNumber, aViolationEventInit.mColumnNumber,
|
||||
nsIScriptError::errorFlag);
|
||||
} else {
|
||||
CSPCONTEXTLOG(("Sent violation report to URI %s", reportURICstring.get()));
|
||||
}
|
||||
|
|
@ -1043,6 +1189,26 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCSPContext::FireViolationEvent(
|
||||
const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mLoadingContext);
|
||||
if (!doc) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::dom::Event> event =
|
||||
mozilla::dom::SecurityPolicyViolationEvent::Constructor(
|
||||
doc,
|
||||
NS_LITERAL_STRING("securitypolicyviolation"),
|
||||
aViolationEventInit);
|
||||
event->SetTrusted(true);
|
||||
|
||||
bool rv;
|
||||
return doc->DispatchEvent(event, &rv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatched from the main thread to send reports for one CSP violation.
|
||||
*/
|
||||
|
|
@ -1058,6 +1224,7 @@ class CSPReportSenderRunnable final : public Runnable
|
|||
const nsAString& aSourceFile,
|
||||
const nsAString& aScriptSample,
|
||||
uint32_t aLineNum,
|
||||
uint32_t aColumnNum,
|
||||
nsCSPContext* aCSPContext)
|
||||
: mBlockedContentSource(aBlockedContentSource)
|
||||
, mOriginalURI(aOriginalURI)
|
||||
|
|
@ -1067,6 +1234,7 @@ class CSPReportSenderRunnable final : public Runnable
|
|||
, mSourceFile(aSourceFile)
|
||||
, mScriptSample(aScriptSample)
|
||||
, mLineNum(aLineNum)
|
||||
, mColumnNum(aColumnNum)
|
||||
, mCSPContext(aCSPContext)
|
||||
{
|
||||
NS_ASSERTION(!aViolatedDirective.IsEmpty(), "Can not send reports without a violated directive");
|
||||
|
|
@ -1088,34 +1256,50 @@ class CSPReportSenderRunnable final : public Runnable
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// 1) notify observers
|
||||
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
|
||||
NS_ASSERTION(observerService, "needs observer service");
|
||||
nsresult rv = observerService->NotifyObservers(mObserverSubject,
|
||||
CSP_VIOLATION_TOPIC,
|
||||
mViolatedDirective.get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsresult rv;
|
||||
|
||||
// 2) send reports for the policy that was violated
|
||||
mCSPContext->SendReports(mBlockedContentSource, mOriginalURI,
|
||||
mViolatedDirective, mViolatedPolicyIndex,
|
||||
mSourceFile, mScriptSample, mLineNum);
|
||||
|
||||
// 3) log to console (one per policy violation)
|
||||
// 0) prepare violation data
|
||||
mozilla::dom::SecurityPolicyViolationEventInit init;
|
||||
// mBlockedContentSource could be a URI or a string.
|
||||
nsCOMPtr<nsIURI> blockedURI = do_QueryInterface(mBlockedContentSource);
|
||||
// if mBlockedContentSource is not a URI, it could be a string
|
||||
nsCOMPtr<nsISupportsCString> blockedString = do_QueryInterface(mBlockedContentSource);
|
||||
nsCOMPtr<nsISupportsCString> blockedICString = do_QueryInterface(mBlockedContentSource);
|
||||
nsAutoCString blockedDataStr;
|
||||
if (blockedICString) {
|
||||
blockedICString->GetData(blockedDataStr);
|
||||
}
|
||||
rv = mCSPContext->GatherSecurityPolicyViolationEventData(
|
||||
blockedURI, blockedDataStr, mOriginalURI,
|
||||
mViolatedDirective, mViolatedPolicyIndex,
|
||||
mSourceFile, mScriptSample, mLineNum,
|
||||
mColumnNum, init);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// 1) notify observers
|
||||
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
|
||||
NS_ASSERTION(observerService, "needs observer service");
|
||||
rv = observerService->NotifyObservers(mObserverSubject,
|
||||
CSP_VIOLATION_TOPIC,
|
||||
mViolatedDirective.get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString blockedDataStr;
|
||||
// 2) send reports for the policy that was violated
|
||||
mCSPContext->SendReports(init, mViolatedPolicyIndex);
|
||||
|
||||
// 3) log to console (one per policy violation)
|
||||
// if mBlockedContentSource is not a URI, it could be a string
|
||||
nsCOMPtr<nsISupportsCString> blockedString = do_QueryInterface(mBlockedContentSource);
|
||||
|
||||
if (blockedURI) {
|
||||
blockedURI->GetSpec(blockedDataStr);
|
||||
bool isData = false;
|
||||
rv = blockedURI->SchemeIs("data", &isData);
|
||||
if (NS_SUCCEEDED(rv) && isData) {
|
||||
blockedDataStr.Truncate(40);
|
||||
blockedDataStr.AppendASCII("...");
|
||||
if (blockedDataStr.Length() > nsCSPContext::ScriptSampleMaxLength()) {
|
||||
bool isData = false;
|
||||
rv = blockedURI->SchemeIs("data", &isData);
|
||||
if (NS_SUCCEEDED(rv) && isData &&
|
||||
blockedDataStr.Length() > nsCSPContext::ScriptSampleMaxLength()) {
|
||||
blockedDataStr.Truncate(nsCSPContext::ScriptSampleMaxLength());
|
||||
blockedDataStr.Append(NS_ConvertUTF16toUTF8(nsContentUtils::GetLocalizedEllipsis()));
|
||||
}
|
||||
}
|
||||
} else if (blockedString) {
|
||||
blockedString->GetData(blockedDataStr);
|
||||
|
|
@ -1128,8 +1312,12 @@ class CSPReportSenderRunnable final : public Runnable
|
|||
mCSPContext->logToConsole(mReportOnlyFlag ? u"CSPROViolationWithURI" :
|
||||
u"CSPViolationWithURI",
|
||||
params, ArrayLength(params), mSourceFile, mScriptSample,
|
||||
mLineNum, 0, nsIScriptError::errorFlag);
|
||||
mLineNum, mColumnNum, nsIScriptError::errorFlag);
|
||||
}
|
||||
|
||||
// 4) fire violation event
|
||||
mCSPContext->FireViolationEvent(init);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1143,6 +1331,7 @@ class CSPReportSenderRunnable final : public Runnable
|
|||
nsString mSourceFile;
|
||||
nsString mScriptSample;
|
||||
uint32_t mLineNum;
|
||||
uint32_t mColumnNum;
|
||||
RefPtr<nsCSPContext> mCSPContext;
|
||||
};
|
||||
|
||||
|
|
@ -1170,6 +1359,8 @@ class CSPReportSenderRunnable final : public Runnable
|
|||
* a sample of the violating inline script
|
||||
* @param aLineNum
|
||||
* source line number of the violation (if available)
|
||||
* @param aColumnNum
|
||||
* source column number of the violation (if available)
|
||||
*/
|
||||
nsresult
|
||||
nsCSPContext::AsyncReportViolation(nsISupports* aBlockedContentSource,
|
||||
|
|
@ -1179,7 +1370,8 @@ nsCSPContext::AsyncReportViolation(nsISupports* aBlockedContentSource,
|
|||
const nsAString& aObserverSubject,
|
||||
const nsAString& aSourceFile,
|
||||
const nsAString& aScriptSample,
|
||||
uint32_t aLineNum)
|
||||
uint32_t aLineNum,
|
||||
uint32_t aColumnNum)
|
||||
{
|
||||
NS_ENSURE_ARG_MAX(aViolatedPolicyIndex, mPolicies.Length() - 1);
|
||||
|
||||
|
|
@ -1192,6 +1384,7 @@ nsCSPContext::AsyncReportViolation(nsISupports* aBlockedContentSource,
|
|||
aSourceFile,
|
||||
aScriptSample,
|
||||
aLineNum,
|
||||
aColumnNum,
|
||||
this));
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#define nsCSPContext_h___
|
||||
|
||||
#include "mozilla/dom/nsCSPUtils.h"
|
||||
#include "mozilla/dom/SecurityPolicyViolationEvent.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
|
|
@ -56,13 +57,43 @@ class nsCSPContext : public nsIContentSecurityPolicy
|
|||
uint32_t aColumnNumber,
|
||||
uint32_t aSeverityFlag);
|
||||
|
||||
nsresult SendReports(nsISupports* aBlockedContentSource,
|
||||
nsIURI* aOriginalURI,
|
||||
nsAString& aViolatedDirective,
|
||||
uint32_t aViolatedPolicyIndex,
|
||||
nsAString& aSourceFile,
|
||||
nsAString& aScriptSample,
|
||||
uint32_t aLineNum);
|
||||
|
||||
/**
|
||||
* Construct SecurityPolicyViolationEventInit structure.
|
||||
*
|
||||
* @param aBlockedURI
|
||||
* A nsIURI: the source of the violation.
|
||||
* @param aOriginalUri
|
||||
* The original URI if the blocked content is a redirect, else null
|
||||
* @param aViolatedDirective
|
||||
* the directive that was violated (string).
|
||||
* @param aSourceFile
|
||||
* name of the file containing the inline script violation
|
||||
* @param aScriptSample
|
||||
* a sample of the violating inline script
|
||||
* @param aLineNum
|
||||
* source line number of the violation (if available)
|
||||
* @param aViolationEventInit
|
||||
* The output
|
||||
*/
|
||||
nsresult GatherSecurityPolicyViolationEventData(
|
||||
nsIURI* aBlockedURI,
|
||||
const nsACString& aBlockedString,
|
||||
nsIURI* aOriginalURI,
|
||||
nsAString& aViolatedDirective,
|
||||
uint32_t aViolatedPolicyIndex,
|
||||
nsAString& aSourceFile,
|
||||
nsAString& aScriptSample,
|
||||
uint32_t aLineNum,
|
||||
uint32_t aColumnNum,
|
||||
mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit);
|
||||
|
||||
nsresult SendReports(
|
||||
const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit,
|
||||
uint32_t aViolatedPolicyIndex);
|
||||
|
||||
nsresult FireViolationEvent(
|
||||
const mozilla::dom::SecurityPolicyViolationEventInit& aViolationEventInit);
|
||||
|
||||
nsresult AsyncReportViolation(nsISupports* aBlockedContentSource,
|
||||
nsIURI* aOriginalURI,
|
||||
|
|
@ -71,7 +102,8 @@ class nsCSPContext : public nsIContentSecurityPolicy
|
|||
const nsAString& aObserverSubject,
|
||||
const nsAString& aSourceFile,
|
||||
const nsAString& aScriptSample,
|
||||
uint32_t aLineNum);
|
||||
uint32_t aLineNum,
|
||||
uint32_t aColumnNum);
|
||||
|
||||
// Hands off! Don't call this method unless you know what you
|
||||
// are doing. It's only supposed to be called from within
|
||||
|
|
@ -80,10 +112,14 @@ class nsCSPContext : public nsIContentSecurityPolicy
|
|||
mLoadingPrincipal = nullptr;
|
||||
}
|
||||
|
||||
nsWeakPtr GetLoadingContext(){
|
||||
nsWeakPtr GetLoadingContext() {
|
||||
return mLoadingContext;
|
||||
}
|
||||
|
||||
static uint32_t ScriptSampleMaxLength() {
|
||||
return std::max(sScriptSampleMaxLength, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
bool permitsInternal(CSPDirective aDir,
|
||||
nsIURI* aContentLocation,
|
||||
|
|
@ -102,7 +138,10 @@ class nsCSPContext : public nsIContentSecurityPolicy
|
|||
const nsAString& aContent,
|
||||
const nsAString& aViolatedDirective,
|
||||
uint32_t aViolatedPolicyIndex,
|
||||
uint32_t aLineNumber);
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber);
|
||||
|
||||
static int32_t sScriptSampleMaxLength;
|
||||
|
||||
nsString mReferrer;
|
||||
uint64_t mInnerWindowID; // used for web console logging
|
||||
|
|
|
|||
|
|
@ -1056,14 +1056,10 @@ nsCSPParser::directiveName()
|
|||
return new nsUpgradeInsecureDirective(CSP_StringToCSPDirective(mCurToken));
|
||||
}
|
||||
|
||||
// child-src by itself is deprecatd but will be enforced
|
||||
// * for workers (if worker-src is not explicitly specified)
|
||||
// * for frames (if frame-src is not explicitly specified)
|
||||
// if we have a child-src, cache it as a fallback for
|
||||
// * workers (if worker-src is not explicitly specified)
|
||||
// * frames (if frame-src is not explicitly specified)
|
||||
if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE)) {
|
||||
const char16_t* params[] = { mCurToken.get() };
|
||||
logWarningErrorToConsole(nsIScriptError::warningFlag,
|
||||
"deprecatedChildSrcDirective",
|
||||
params, ArrayLength(params));
|
||||
mChildSrc = new nsCSPChildSrcDirective(CSP_StringToCSPDirective(mCurToken));
|
||||
return mChildSrc;
|
||||
}
|
||||
|
|
@ -1115,6 +1111,10 @@ nsCSPParser::directive()
|
|||
return;
|
||||
}
|
||||
|
||||
if (CSP_IsEmptyDirective(mCurValue, mCurToken)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to create a new CSPDirective
|
||||
nsCSPDirective* cspDir = directiveName();
|
||||
if (!cspDir) {
|
||||
|
|
|
|||
|
|
@ -212,6 +212,7 @@ CSP_ContentTypeToDirective(nsContentPolicyType aType)
|
|||
case nsIContentPolicy::TYPE_SCRIPT:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS:
|
||||
return nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE;
|
||||
|
||||
case nsIContentPolicy::TYPE_STYLESHEET:
|
||||
|
|
@ -292,6 +293,13 @@ CSP_CreateHostSrcFromSelfURI(nsIURI* aSelfURI)
|
|||
return hostsrc;
|
||||
}
|
||||
|
||||
bool
|
||||
CSP_IsEmptyDirective(const nsAString& aValue, const nsAString& aDir)
|
||||
{
|
||||
return (aDir.Length() == 0 &&
|
||||
aValue.Length() == 0);
|
||||
}
|
||||
|
||||
bool
|
||||
CSP_IsValidDirective(const nsAString& aDir)
|
||||
{
|
||||
|
|
@ -1257,6 +1265,12 @@ bool nsCSPDirective::equals(CSPDirective aDirective) const
|
|||
return (mDirective == aDirective);
|
||||
}
|
||||
|
||||
void
|
||||
nsCSPDirective::getDirName(nsAString& outStr) const
|
||||
{
|
||||
outStr.AppendASCII(CSP_CSPDirectiveToString(mDirective));
|
||||
}
|
||||
|
||||
/* =============== nsCSPChildSrcDirective ============= */
|
||||
|
||||
nsCSPChildSrcDirective::nsCSPChildSrcDirective(CSPDirective aDirective)
|
||||
|
|
@ -1342,6 +1356,13 @@ nsBlockAllMixedContentDirective::toString(nsAString& outStr) const
|
|||
nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT));
|
||||
}
|
||||
|
||||
void
|
||||
nsBlockAllMixedContentDirective::getDirName(nsAString& outStr) const
|
||||
{
|
||||
outStr.AppendASCII(CSP_CSPDirectiveToString(
|
||||
nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT));
|
||||
}
|
||||
|
||||
/* =============== nsUpgradeInsecureDirective ============= */
|
||||
|
||||
nsUpgradeInsecureDirective::nsUpgradeInsecureDirective(CSPDirective aDirective)
|
||||
|
|
@ -1360,6 +1381,13 @@ nsUpgradeInsecureDirective::toString(nsAString& outStr) const
|
|||
nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE));
|
||||
}
|
||||
|
||||
void
|
||||
nsUpgradeInsecureDirective::getDirName(nsAString& outStr) const
|
||||
{
|
||||
outStr.AppendASCII(CSP_CSPDirectiveToString(
|
||||
nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE));
|
||||
}
|
||||
|
||||
/* ===== nsRequireSRIForDirective ========================= */
|
||||
|
||||
nsRequireSRIForDirective::nsRequireSRIForDirective(CSPDirective aDirective)
|
||||
|
|
@ -1411,6 +1439,13 @@ nsRequireSRIForDirective::allows(enum CSPKeyword aKeyword, const nsAString& aHas
|
|||
return (aKeyword != CSP_REQUIRE_SRI_FOR);
|
||||
}
|
||||
|
||||
void
|
||||
nsRequireSRIForDirective::getDirName(nsAString& outStr) const
|
||||
{
|
||||
outStr.AppendASCII(CSP_CSPDirectiveToString(
|
||||
nsIContentSecurityPolicy::REQUIRE_SRI_FOR));
|
||||
}
|
||||
|
||||
/* ===== nsCSPPolicy ========================= */
|
||||
|
||||
nsCSPPolicy::nsCSPPolicy()
|
||||
|
|
@ -1464,7 +1499,7 @@ nsCSPPolicy::permits(CSPDirective aDir,
|
|||
if (mDirectives[i]->equals(aDir)) {
|
||||
if (!mDirectives[i]->permits(aUri, aNonce, aWasRedirected, mReportOnly,
|
||||
mUpgradeInsecDir, aParserCreated)) {
|
||||
mDirectives[i]->toString(outViolatedDirective);
|
||||
mDirectives[i]->getDirName(outViolatedDirective);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -1479,7 +1514,7 @@ nsCSPPolicy::permits(CSPDirective aDir,
|
|||
if (!aSpecific && defaultDir) {
|
||||
if (!defaultDir->permits(aUri, aNonce, aWasRedirected, mReportOnly,
|
||||
mUpgradeInsecDir, aParserCreated)) {
|
||||
defaultDir->toString(outViolatedDirective);
|
||||
defaultDir->getDirName(outViolatedDirective);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -1605,7 +1640,7 @@ nsCSPPolicy::getDirectiveStringForContentType(nsContentPolicyType aContentType,
|
|||
nsCSPDirective* defaultDir = nullptr;
|
||||
for (uint32_t i = 0; i < mDirectives.Length(); i++) {
|
||||
if (mDirectives[i]->restrictsContentType(aContentType)) {
|
||||
mDirectives[i]->toString(outDirective);
|
||||
mDirectives[i]->getDirName(outDirective);
|
||||
return;
|
||||
}
|
||||
if (mDirectives[i]->isDefaultDirective()) {
|
||||
|
|
@ -1615,7 +1650,7 @@ nsCSPPolicy::getDirectiveStringForContentType(nsContentPolicyType aContentType,
|
|||
// if we haven't found a matching directive yet,
|
||||
// the contentType must be restricted by the default directive
|
||||
if (defaultDir) {
|
||||
defaultDir->toString(outDirective);
|
||||
defaultDir->getDirName(outDirective);
|
||||
return;
|
||||
}
|
||||
NS_ASSERTION(false, "Can not query directive string for contentType!");
|
||||
|
|
|
|||
|
|
@ -235,6 +235,7 @@ nsresult CSP_AppendCSPFromHeader(nsIContentSecurityPolicy* aCsp,
|
|||
class nsCSPHostSrc;
|
||||
|
||||
nsCSPHostSrc* CSP_CreateHostSrcFromSelfURI(nsIURI* aSelfURI);
|
||||
bool CSP_IsEmptyDirective(const nsAString& aValue, const nsAString& aDir);
|
||||
bool CSP_IsValidDirective(const nsAString& aDir);
|
||||
bool CSP_IsDirective(const nsAString& aValue, CSPDirective aDir);
|
||||
bool CSP_IsKeyword(const nsAString& aValue, enum CSPKeyword aKey);
|
||||
|
|
@ -493,6 +494,8 @@ class nsCSPDirective {
|
|||
|
||||
bool visitSrcs(nsCSPSrcVisitor* aVisitor) const;
|
||||
|
||||
virtual void getDirName(nsAString& outStr) const;
|
||||
|
||||
protected:
|
||||
CSPDirective mDirective;
|
||||
nsTArray<nsCSPBaseSrc*> mSrcs;
|
||||
|
|
@ -571,6 +574,8 @@ class nsBlockAllMixedContentDirective : public nsCSPDirective {
|
|||
|
||||
void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs)
|
||||
{ MOZ_ASSERT(false, "block-all-mixed-content does not hold any srcs"); }
|
||||
|
||||
void getDirName(nsAString& outStr) const override;
|
||||
};
|
||||
|
||||
/* =============== nsUpgradeInsecureDirective === */
|
||||
|
|
@ -624,6 +629,8 @@ class nsUpgradeInsecureDirective : public nsCSPDirective {
|
|||
|
||||
void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs)
|
||||
{ MOZ_ASSERT(false, "upgrade-insecure-requests does not hold any srcs"); }
|
||||
|
||||
void getDirName(nsAString& outStr) const override;
|
||||
};
|
||||
|
||||
/* ===== nsRequireSRIForDirective ========================= */
|
||||
|
|
@ -641,6 +648,7 @@ class nsRequireSRIForDirective : public nsCSPDirective {
|
|||
bool restrictsContentType(nsContentPolicyType aType) const;
|
||||
bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce,
|
||||
bool aParserCreated) const;
|
||||
void getDirName(nsAString& outStr) const override;
|
||||
|
||||
private:
|
||||
nsTArray<nsContentPolicyType> mTypes;
|
||||
|
|
|
|||
|
|
@ -405,7 +405,7 @@ nsSMILCSSValueType::ValueFromString(nsCSSPropertyID aPropID,
|
|||
if (doc && !nsStyleUtil::CSPAllowsInlineStyle(nullptr,
|
||||
doc->NodePrincipal(),
|
||||
doc->GetDocumentURI(),
|
||||
0, aString, nullptr)) {
|
||||
0, 0, aString, nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ dictionary CSPReportProperties {
|
|||
DOMString source-file;
|
||||
DOMString script-sample;
|
||||
long line-number;
|
||||
long column-number;
|
||||
};
|
||||
|
||||
dictionary CSPReport {
|
||||
|
|
|
|||
41
dom/webidl/SecurityPolicyViolationEvent.webidl
Normal file
41
dom/webidl/SecurityPolicyViolationEvent.webidl
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
enum SecurityPolicyViolationEventDisposition
|
||||
{
|
||||
"enforce", "report"
|
||||
};
|
||||
|
||||
[Constructor(DOMString type, optional SecurityPolicyViolationEventInit eventInitDict)]
|
||||
interface SecurityPolicyViolationEvent : Event
|
||||
{
|
||||
readonly attribute DOMString documentURI;
|
||||
readonly attribute DOMString referrer;
|
||||
readonly attribute DOMString blockedURI;
|
||||
readonly attribute DOMString violatedDirective;
|
||||
readonly attribute DOMString effectiveDirective;
|
||||
readonly attribute DOMString originalPolicy;
|
||||
readonly attribute DOMString sourceFile;
|
||||
readonly attribute DOMString sample;
|
||||
readonly attribute SecurityPolicyViolationEventDisposition disposition;
|
||||
readonly attribute unsigned short statusCode;
|
||||
readonly attribute long lineNumber;
|
||||
readonly attribute long columnNumber;
|
||||
};
|
||||
|
||||
dictionary SecurityPolicyViolationEventInit : EventInit
|
||||
{
|
||||
DOMString documentURI = "";
|
||||
DOMString referrer = "";
|
||||
DOMString blockedURI = "";
|
||||
DOMString violatedDirective = "";
|
||||
DOMString effectiveDirective = "";
|
||||
DOMString originalPolicy = "";
|
||||
DOMString sourceFile = "";
|
||||
DOMString sample = "";
|
||||
SecurityPolicyViolationEventDisposition disposition = "report";
|
||||
unsigned short statusCode = 0;
|
||||
long lineNumber = 0;
|
||||
long columnNumber = 0;
|
||||
};
|
||||
|
|
@ -694,6 +694,7 @@ GENERATED_EVENTS_WEBIDL_FILES = [
|
|||
'PromiseRejectionEvent.webidl',
|
||||
'RecordErrorEvent.webidl',
|
||||
'ScrollViewChangeEvent.webidl',
|
||||
'SecurityPolicyViolationEvent.webidl',
|
||||
'ServiceWorkerMessageEvent.webidl',
|
||||
'StyleRuleChangeEvent.webidl',
|
||||
'StyleSheetApplicableStateChangeEvent.webidl',
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#ifndef mozilla_dom_workers_queue_h__
|
||||
#define mozilla_dom_workers_queue_h__
|
||||
|
||||
#include "Workers.h"
|
||||
#include "mozilla/dom/workers/Workers.h"
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsTArray.h"
|
||||
|
|
|
|||
|
|
@ -547,14 +547,21 @@ class LogViolationDetailsRunnable final : public WorkerMainThreadRunnable
|
|||
{
|
||||
nsString mFileName;
|
||||
uint32_t mLineNum;
|
||||
uint32_t mColumnNum;
|
||||
nsString mScriptSample;
|
||||
|
||||
public:
|
||||
LogViolationDetailsRunnable(WorkerPrivate* aWorker,
|
||||
const nsString& aFileName,
|
||||
uint32_t aLineNum)
|
||||
uint32_t aLineNum,
|
||||
uint32_t aColumnNum,
|
||||
const nsAString& aScriptSample)
|
||||
: WorkerMainThreadRunnable(aWorker,
|
||||
NS_LITERAL_CSTRING("RuntimeService :: LogViolationDetails"))
|
||||
, mFileName(aFileName), mLineNum(aLineNum)
|
||||
, mFileName(aFileName)
|
||||
, mLineNum(aLineNum)
|
||||
, mColumnNum(aColumnNum)
|
||||
, mScriptSample(aScriptSample)
|
||||
{
|
||||
MOZ_ASSERT(aWorker);
|
||||
}
|
||||
|
|
@ -566,24 +573,38 @@ private:
|
|||
};
|
||||
|
||||
bool
|
||||
ContentSecurityPolicyAllows(JSContext* aCx)
|
||||
ContentSecurityPolicyAllows(JSContext* aCx, JS::HandleValue aValue)
|
||||
{
|
||||
WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx);
|
||||
worker->AssertIsOnWorkerThread();
|
||||
|
||||
if (worker->GetReportCSPViolations()) {
|
||||
JS::Rooted<JSString*> jsString(aCx, JS::ToString(aCx, aValue));
|
||||
if (NS_WARN_IF(!jsString)) {
|
||||
JS_ClearPendingException(aCx);
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoJSString scriptSample;
|
||||
if (NS_WARN_IF(!scriptSample.init(aCx, jsString))) {
|
||||
JS_ClearPendingException(aCx);
|
||||
return false;
|
||||
}
|
||||
|
||||
nsString fileName;
|
||||
uint32_t lineNum = 0;
|
||||
uint32_t columnNum = 0;
|
||||
|
||||
JS::AutoFilename file;
|
||||
if (JS::DescribeScriptedCaller(aCx, &file, &lineNum) && file.get()) {
|
||||
if (JS::DescribeScriptedCaller(aCx, &file, &lineNum, &columnNum) && file.get()) {
|
||||
fileName = NS_ConvertUTF8toUTF16(file.get());
|
||||
} else {
|
||||
MOZ_ASSERT(!JS_IsExceptionPending(aCx));
|
||||
}
|
||||
|
||||
RefPtr<LogViolationDetailsRunnable> runnable =
|
||||
new LogViolationDetailsRunnable(worker, fileName, lineNum);
|
||||
new LogViolationDetailsRunnable(worker, fileName, lineNum, columnNum,
|
||||
scriptSample);
|
||||
|
||||
ErrorResult rv;
|
||||
runnable->Dispatch(Killing, rv);
|
||||
|
|
@ -2698,11 +2719,9 @@ LogViolationDetailsRunnable::MainThreadRun()
|
|||
|
||||
nsIContentSecurityPolicy* csp = mWorkerPrivate->GetCSP();
|
||||
if (csp) {
|
||||
NS_NAMED_LITERAL_STRING(scriptSample,
|
||||
"Call to eval() or related function blocked by CSP.");
|
||||
if (mWorkerPrivate->GetReportCSPViolations()) {
|
||||
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
|
||||
mFileName, scriptSample, mLineNum,
|
||||
mFileName, mScriptSample, mLineNum, mColumnNum,
|
||||
EmptyString(), EmptyString());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@
|
|||
#include "mozilla/dom/ScriptLoader.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/SRILogHelper.h"
|
||||
#include "mozilla/dom/workers/ServiceWorkerManager.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "Principal.h"
|
||||
#include "WorkerHolder.h"
|
||||
|
|
@ -112,7 +113,7 @@ ChannelFromScriptURL(nsIPrincipal* principal,
|
|||
const nsAString& aScriptURL,
|
||||
bool aIsMainScript,
|
||||
WorkerScriptType aWorkerScriptType,
|
||||
nsContentPolicyType aContentPolicyType,
|
||||
nsContentPolicyType aMainScriptContentPolicyType,
|
||||
nsLoadFlags aLoadFlags,
|
||||
bool aDefaultURIEncoding,
|
||||
nsIChannel** aChannel)
|
||||
|
|
@ -169,6 +170,10 @@ ChannelFromScriptURL(nsIPrincipal* principal,
|
|||
secFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
|
||||
}
|
||||
|
||||
nsContentPolicyType contentPolicyType =
|
||||
aIsMainScript ? aMainScriptContentPolicyType
|
||||
: nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS;
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
// If we have the document, use it. Unfortunately, for dedicated workers
|
||||
// 'parentDoc' ends up being the parent document, which is not the document
|
||||
|
|
@ -179,7 +184,7 @@ ChannelFromScriptURL(nsIPrincipal* principal,
|
|||
uri,
|
||||
parentDoc,
|
||||
secFlags,
|
||||
aContentPolicyType,
|
||||
contentPolicyType,
|
||||
loadGroup,
|
||||
nullptr, // aCallbacks
|
||||
aLoadFlags,
|
||||
|
|
@ -194,7 +199,7 @@ ChannelFromScriptURL(nsIPrincipal* principal,
|
|||
uri,
|
||||
principal,
|
||||
secFlags,
|
||||
aContentPolicyType,
|
||||
contentPolicyType,
|
||||
loadGroup,
|
||||
nullptr, // aCallbacks
|
||||
aLoadFlags,
|
||||
|
|
@ -464,6 +469,8 @@ private:
|
|||
nsCOMPtr<nsIURI> mBaseURI;
|
||||
mozilla::dom::ChannelInfo mChannelInfo;
|
||||
UniquePtr<PrincipalInfo> mPrincipalInfo;
|
||||
nsCString mCSPHeaderValue;
|
||||
nsCString mCSPReportOnlyHeaderValue;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(CacheScriptLoader, nsIStreamLoaderObserver)
|
||||
|
|
@ -657,6 +664,34 @@ private:
|
|||
ScriptLoadInfo& loadInfo = mLoadInfos[aIndex];
|
||||
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
||||
|
||||
// Checking the MIME type is only required for ServiceWorkers'
|
||||
// importScripts, per step 10 of https://w3c.github.io/ServiceWorker/#importscripts
|
||||
//
|
||||
// "Extract a MIME type from the response’s header list. If this MIME type
|
||||
// (ignoring parameters) is not a JavaScript MIME type, return a network error."
|
||||
if (mWorkerPrivate->IsServiceWorker()) {
|
||||
nsAutoCString mimeType;
|
||||
channel->GetContentType(mimeType);
|
||||
|
||||
if (!nsContentUtils::IsJavascriptMIMEType(NS_ConvertUTF8toUTF16(mimeType))) {
|
||||
const nsCString& scope =
|
||||
mWorkerPrivate->ServiceWorkerScope();
|
||||
|
||||
ServiceWorkerManager::LocalizeAndReportToAllClients(
|
||||
scope, "ServiceWorkerRegisterMimeTypeError2",
|
||||
nsTArray<nsString> {
|
||||
NS_ConvertUTF8toUTF16(scope),
|
||||
NS_ConvertUTF8toUTF16(mimeType),
|
||||
loadInfo.mURL
|
||||
}
|
||||
);
|
||||
|
||||
channel->Cancel(NS_ERROR_DOM_NETWORK_ERR);
|
||||
return NS_ERROR_DOM_NETWORK_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(channel == loadInfo.mChannel);
|
||||
|
||||
// We synthesize the result code, but its never exposed to content.
|
||||
|
|
@ -691,6 +726,7 @@ private:
|
|||
}
|
||||
|
||||
ir->SetPrincipalInfo(Move(principalInfo));
|
||||
ir->Headers()->FillResponseHeaders(loadInfo.mChannel);
|
||||
|
||||
RefPtr<mozilla::dom::Response> response =
|
||||
new mozilla::dom::Response(mCacheCreator->Global(), ir, nullptr);
|
||||
|
|
@ -1127,11 +1163,11 @@ private:
|
|||
("Scriptloader::Load, SRI required but not supported in workers"));
|
||||
nsCOMPtr<nsIContentSecurityPolicy> wcsp;
|
||||
chanLoadInfo->LoadingPrincipal()->GetCsp(getter_AddRefs(wcsp));
|
||||
MOZ_ASSERT(wcsp, "We sould have a CSP for the worker here");
|
||||
MOZ_ASSERT(wcsp, "We should have a CSP for the worker here");
|
||||
if (wcsp) {
|
||||
wcsp->LogViolationDetails(
|
||||
nsIContentSecurityPolicy::VIOLATION_TYPE_REQUIRE_SRI_FOR_SCRIPT,
|
||||
aLoadInfo.mURL, EmptyString(), 0, EmptyString(), EmptyString());
|
||||
aLoadInfo.mURL, EmptyString(), 0, 0, EmptyString(), EmptyString());
|
||||
}
|
||||
return NS_ERROR_SRI_CORRUPT;
|
||||
}
|
||||
|
|
@ -1199,53 +1235,14 @@ private:
|
|||
// load group's appId and browser element flag.
|
||||
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(channelLoadGroup, channelPrincipal));
|
||||
|
||||
mWorkerPrivate->SetPrincipal(channelPrincipal, channelLoadGroup);
|
||||
mWorkerPrivate->SetPrincipalOnMainThread(channelPrincipal, channelLoadGroup);
|
||||
|
||||
// We did inherit CSP in bug 1223647. If we do not already have a CSP, we
|
||||
// should get it from the HTTP headers on the worker script.
|
||||
if (!mWorkerPrivate->GetCSP() && CSPService::sCSPEnabled) {
|
||||
NS_ConvertASCIItoUTF16 cspHeaderValue(tCspHeaderValue);
|
||||
NS_ConvertASCIItoUTF16 cspROHeaderValue(tCspROHeaderValue);
|
||||
|
||||
nsIPrincipal* principal = mWorkerPrivate->GetPrincipal();
|
||||
MOZ_ASSERT(principal, "Should not be null");
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
rv = principal->EnsureCSP(nullptr, getter_AddRefs(csp));
|
||||
|
||||
if (csp) {
|
||||
// If there's a CSP header, apply it.
|
||||
if (!cspHeaderValue.IsEmpty()) {
|
||||
rv = CSP_AppendCSPFromHeader(csp, cspHeaderValue, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
// If there's a report-only CSP header, apply it.
|
||||
if (!cspROHeaderValue.IsEmpty()) {
|
||||
rv = CSP_AppendCSPFromHeader(csp, cspROHeaderValue, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Set evalAllowed, default value is set in GetAllowsEval
|
||||
bool evalAllowed = false;
|
||||
bool reportEvalViolations = false;
|
||||
rv = csp->GetAllowsEval(&reportEvalViolations, &evalAllowed);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mWorkerPrivate->SetCSP(csp);
|
||||
mWorkerPrivate->SetEvalAllowed(evalAllowed);
|
||||
mWorkerPrivate->SetReportCSPViolations(reportEvalViolations);
|
||||
|
||||
// Set ReferrerPolicy, default value is set in GetReferrerPolicy
|
||||
bool hasReferrerPolicy = false;
|
||||
uint32_t rp = mozilla::net::RP_Default;
|
||||
rv = csp->GetReferrerPolicy(&rp, &hasReferrerPolicy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
||||
if (hasReferrerPolicy) { //FIXME bug 1307366: move RP out of CSP code
|
||||
mWorkerPrivate->SetReferrerPolicy(static_cast<net::ReferrerPolicy>(rp));
|
||||
}
|
||||
}
|
||||
rv = mWorkerPrivate->SetCSPFromHeaderValues(tCspHeaderValue,
|
||||
tCspROHeaderValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
if (parent) {
|
||||
// XHR Params Allowed
|
||||
|
|
@ -1270,7 +1267,9 @@ private:
|
|||
DataReceivedFromCache(uint32_t aIndex, const uint8_t* aString,
|
||||
uint32_t aStringLen,
|
||||
const mozilla::dom::ChannelInfo& aChannelInfo,
|
||||
UniquePtr<PrincipalInfo> aPrincipalInfo)
|
||||
UniquePtr<PrincipalInfo> aPrincipalInfo,
|
||||
const nsACString& aCSPHeaderValue,
|
||||
const nsACString& aCSPReportOnlyHeaderValue)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aIndex < mLoadInfos.Length());
|
||||
|
|
@ -1279,6 +1278,7 @@ private:
|
|||
|
||||
nsCOMPtr<nsIPrincipal> responsePrincipal =
|
||||
PrincipalInfoToPrincipal(*aPrincipalInfo);
|
||||
MOZ_DIAGNOSTIC_ASSERT(responsePrincipal);
|
||||
|
||||
nsIPrincipal* principal = mWorkerPrivate->GetPrincipal();
|
||||
if (!principal) {
|
||||
|
|
@ -1306,17 +1306,35 @@ private:
|
|||
mWorkerPrivate->SetBaseURI(finalURI);
|
||||
}
|
||||
|
||||
mozilla::DebugOnly<nsIPrincipal*> principal = mWorkerPrivate->GetPrincipal();
|
||||
MOZ_ASSERT(principal);
|
||||
nsILoadGroup* loadGroup = mWorkerPrivate->GetLoadGroup();
|
||||
MOZ_ASSERT(loadGroup);
|
||||
MOZ_DIAGNOSTIC_ASSERT(loadGroup);
|
||||
|
||||
mozilla::DebugOnly<bool> equal = false;
|
||||
MOZ_ASSERT(responsePrincipal && NS_SUCCEEDED(responsePrincipal->Equals(principal, &equal)));
|
||||
MOZ_ASSERT(equal);
|
||||
#if defined(DEBUG)
|
||||
nsIPrincipal* principal = mWorkerPrivate->GetPrincipal();
|
||||
MOZ_DIAGNOSTIC_ASSERT(principal);
|
||||
|
||||
bool equal = false;
|
||||
MOZ_ALWAYS_SUCCEEDS(responsePrincipal->Equals(principal, &equal));
|
||||
MOZ_DIAGNOSTIC_ASSERT(equal);
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
MOZ_ALWAYS_SUCCEEDS(responsePrincipal->GetCsp(getter_AddRefs(csp)));
|
||||
MOZ_DIAGNOSTIC_ASSERT(!csp);
|
||||
#endif
|
||||
|
||||
mWorkerPrivate->InitChannelInfo(aChannelInfo);
|
||||
mWorkerPrivate->SetPrincipal(responsePrincipal, loadGroup);
|
||||
|
||||
// Override the principal on the WorkerPrivate. We just asserted that
|
||||
// this is the same as our current WorkerPrivate principal, so this is
|
||||
// almost a no-op. We must do, it though, in order to avoid accidentally
|
||||
// propagating the CSP object back to the ServiceWorkerRegistration
|
||||
// principal. If bug 965637 is fixed then this can be removed.
|
||||
rv = mWorkerPrivate->SetPrincipalOnMainThread(responsePrincipal, loadGroup);
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
rv = mWorkerPrivate->SetCSPFromHeaderValues(aCSPHeaderValue,
|
||||
aCSPReportOnlyHeaderValue);
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
|
@ -1730,6 +1748,14 @@ CacheScriptLoader::ResolvedCallback(JSContext* aCx,
|
|||
return;
|
||||
}
|
||||
|
||||
InternalHeaders* headers = response->GetInternalHeaders();
|
||||
|
||||
IgnoredErrorResult ignored;
|
||||
headers->Get(NS_LITERAL_CSTRING("content-security-policy"),
|
||||
mCSPHeaderValue, ignored);
|
||||
headers->Get(NS_LITERAL_CSTRING("content-security-policy-report-only"),
|
||||
mCSPReportOnlyHeaderValue, ignored);
|
||||
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
response->GetBody(getter_AddRefs(inputStream));
|
||||
mChannelInfo = response->GetChannelInfo();
|
||||
|
|
@ -1741,7 +1767,8 @@ CacheScriptLoader::ResolvedCallback(JSContext* aCx,
|
|||
if (!inputStream) {
|
||||
mLoadInfo.mCacheStatus = ScriptLoadInfo::Cached;
|
||||
mRunnable->DataReceivedFromCache(mIndex, (uint8_t*)"", 0, mChannelInfo,
|
||||
Move(mPrincipalInfo));
|
||||
Move(mPrincipalInfo), mCSPHeaderValue,
|
||||
mCSPReportOnlyHeaderValue);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1801,7 +1828,8 @@ CacheScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aCont
|
|||
|
||||
MOZ_ASSERT(mPrincipalInfo);
|
||||
mRunnable->DataReceivedFromCache(mIndex, aString, aStringLen, mChannelInfo,
|
||||
Move(mPrincipalInfo));
|
||||
Move(mPrincipalInfo), mCSPHeaderValue,
|
||||
mCSPReportOnlyHeaderValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
@ -2170,7 +2198,7 @@ ChannelFromScriptURLMainThread(nsIPrincipal* aPrincipal,
|
|||
nsIDocument* aParentDoc,
|
||||
nsILoadGroup* aLoadGroup,
|
||||
const nsAString& aScriptURL,
|
||||
nsContentPolicyType aContentPolicyType,
|
||||
nsContentPolicyType aMainScriptContentPolicyType,
|
||||
bool aDefaultURIEncoding,
|
||||
nsIChannel** aChannel)
|
||||
{
|
||||
|
|
@ -2183,8 +2211,9 @@ ChannelFromScriptURLMainThread(nsIPrincipal* aPrincipal,
|
|||
|
||||
return ChannelFromScriptURL(aPrincipal, aBaseURI, aParentDoc, aLoadGroup,
|
||||
ios, secMan, aScriptURL, true, WorkerScript,
|
||||
aContentPolicyType, nsIRequest::LOAD_NORMAL,
|
||||
aDefaultURIEncoding, aChannel);
|
||||
aMainScriptContentPolicyType,
|
||||
nsIRequest::LOAD_NORMAL, aDefaultURIEncoding,
|
||||
aChannel);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
|||
|
|
@ -805,7 +805,7 @@ public:
|
|||
|
||||
WaitUntilHandler(WorkerPrivate* aWorkerPrivate, JSContext* aCx)
|
||||
: mWorkerPrivate(aWorkerPrivate)
|
||||
, mScope(mWorkerPrivate->WorkerName())
|
||||
, mScope(mWorkerPrivate->ServiceWorkerScope())
|
||||
, mLine(0)
|
||||
, mColumn(0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3154,10 +3154,12 @@ already_AddRefed<ServiceWorkerRegistrationInfo>
|
|||
ServiceWorkerManager::CreateNewRegistration(const nsCString& aScope,
|
||||
nsIPrincipal* aPrincipal)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
#ifdef DEBUG
|
||||
AssertIsOnMainThread();
|
||||
nsCOMPtr<nsIURI> scopeURI;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), aScope, nullptr, nullptr);
|
||||
rv = NS_NewURI(getter_AddRefs(scopeURI), aScope, nullptr, nullptr);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> tmp =
|
||||
|
|
@ -3165,8 +3167,35 @@ ServiceWorkerManager::CreateNewRegistration(const nsCString& aScope,
|
|||
MOZ_ASSERT(!tmp);
|
||||
#endif
|
||||
|
||||
// The environment that registers the document may have some CSP applied
|
||||
// to its principal. This should not be inherited by the registration
|
||||
// itself or the worker it creates. To avoid confusion in callsites
|
||||
// downstream we strip the CSP from the principal now.
|
||||
//
|
||||
// Unfortunately there is no API to clone a principal without its CSP. To
|
||||
// achieve the same thing we serialize to the IPC PrincipalInfo type and
|
||||
// back to an nsIPrincipal.
|
||||
PrincipalInfo principalInfo;
|
||||
rv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> cleanPrincipal =
|
||||
PrincipalInfoToPrincipal(principalInfo, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Verify that we do not have any CSP set on our principal "clone".
|
||||
#if defined(DEBUG) || !defined(RELEASE_OR_BETA)
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
MOZ_ALWAYS_SUCCEEDS(cleanPrincipal->GetCsp(getter_AddRefs(csp)));
|
||||
MOZ_DIAGNOSTIC_ASSERT(!csp);
|
||||
#endif
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
new ServiceWorkerRegistrationInfo(aScope, aPrincipal);
|
||||
new ServiceWorkerRegistrationInfo(aScope, cleanPrincipal);
|
||||
// From now on ownership of registration is with
|
||||
// mServiceWorkerRegistrationInfos.
|
||||
AddScopeAndRegistration(aScope, registration);
|
||||
|
|
|
|||
|
|
@ -1760,26 +1760,30 @@ ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
|
|||
info.mStorageAllowed = access > nsContentUtils::StorageAccess::ePrivateBrowsing;
|
||||
info.mOriginAttributes = mInfo->GetOriginAttributes();
|
||||
|
||||
// The ServiceWorkerRegistration principal should never have any CSP
|
||||
// set. The CSP from the page that registered the SW should not be
|
||||
// inherited. Verify this is the case in non-release builds
|
||||
#if defined(DEBUG)
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
rv = info.mPrincipal->GetCsp(getter_AddRefs(csp));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
MOZ_DIAGNOSTIC_ASSERT(!csp);
|
||||
#endif
|
||||
|
||||
info.mCSP = csp;
|
||||
if (info.mCSP) {
|
||||
rv = info.mCSP->GetAllowsEval(&info.mReportCSPViolations,
|
||||
&info.mEvalAllowed);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
info.mEvalAllowed = true;
|
||||
info.mReportCSPViolations = false;
|
||||
}
|
||||
// Default CSP permissions for now. These will be overrided if necessary
|
||||
// based on the script CSP headers during load in ScriptLoader.
|
||||
info.mEvalAllowed = true;
|
||||
info.mReportCSPViolations = false;
|
||||
|
||||
WorkerPrivate::OverrideLoadInfoLoadGroup(info);
|
||||
|
||||
rv = info.SetPrincipalOnMainThread(info.mPrincipal, info.mLoadGroup);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
ErrorResult error;
|
||||
|
|
|
|||
|
|
@ -52,6 +52,11 @@ ServiceWorkerRegisterJob::AsyncExecute()
|
|||
}
|
||||
} else {
|
||||
registration = swm->CreateNewRegistration(mScope, mPrincipal);
|
||||
|
||||
if (!registration) {
|
||||
FailUpdateJob(NS_ERROR_DOM_ABORT_ERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetRegistration(registration);
|
||||
|
|
|
|||
|
|
@ -239,6 +239,7 @@ public:
|
|||
CompareCallback* aCallback)
|
||||
: mRegistration(aRegistration)
|
||||
, mCallback(aCallback)
|
||||
, mInternalHeaders(new InternalHeaders())
|
||||
, mState(WaitingForOpen)
|
||||
, mNetworkFinished(false)
|
||||
, mCacheFinished(false)
|
||||
|
|
@ -425,11 +426,21 @@ public:
|
|||
return mCacheStorage;
|
||||
}
|
||||
|
||||
void
|
||||
InitChannelInfo(nsIChannel* aChannel)
|
||||
nsresult
|
||||
OnStartRequest(nsIChannel* aChannel)
|
||||
{
|
||||
nsresult rv = SetPrincipalInfo(aChannel);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mChannelInfo.InitFromChannel(aChannel);
|
||||
|
||||
mInternalHeaders->FillResponseHeaders(aChannel);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
SetPrincipalInfo(nsIChannel* aChannel)
|
||||
|
|
@ -553,6 +564,9 @@ private:
|
|||
ir->SetPrincipalInfo(Move(mPrincipalInfo));
|
||||
}
|
||||
|
||||
IgnoredErrorResult ignored;
|
||||
ir->Headers()->Fill(*mInternalHeaders, ignored);
|
||||
|
||||
RefPtr<Response> response = new Response(aCache->GetGlobalObject(), ir, nullptr);
|
||||
|
||||
RequestOrUSVString request;
|
||||
|
|
@ -587,6 +601,7 @@ private:
|
|||
nsString mNewCacheName;
|
||||
|
||||
ChannelInfo mChannelInfo;
|
||||
RefPtr<InternalHeaders> mInternalHeaders;
|
||||
|
||||
UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
|
||||
|
||||
|
|
@ -682,8 +697,7 @@ CompareNetwork::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
|
|||
MOZ_ASSERT(channel == mChannel);
|
||||
#endif
|
||||
|
||||
mManager->InitChannelInfo(mChannel);
|
||||
nsresult rv = mManager->SetPrincipalInfo(mChannel);
|
||||
nsresult rv = mManager->OnStartRequest(mChannel);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
|
@ -787,12 +801,11 @@ CompareNetwork::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext
|
|||
return rv;
|
||||
}
|
||||
|
||||
if (!mimeType.LowerCaseEqualsLiteral("text/javascript") &&
|
||||
!mimeType.LowerCaseEqualsLiteral("application/x-javascript") &&
|
||||
!mimeType.LowerCaseEqualsLiteral("application/javascript")) {
|
||||
if (mimeType.IsEmpty() ||
|
||||
!nsContentUtils::IsJavascriptMIMEType(NS_ConvertUTF8toUTF16(mimeType))) {
|
||||
RefPtr<ServiceWorkerRegistrationInfo> registration = mManager->GetRegistration();
|
||||
ServiceWorkerManager::LocalizeAndReportToAllClients(
|
||||
registration->mScope, "ServiceWorkerRegisterMimeTypeError",
|
||||
registration->mScope, "ServiceWorkerRegisterMimeTypeError2",
|
||||
nsTArray<nsString> { NS_ConvertUTF8toUTF16(registration->mScope),
|
||||
NS_ConvertUTF8toUTF16(mimeType), mManager->URL() });
|
||||
mManager->NetworkFinished(NS_ERROR_DOM_SECURITY_ERR);
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@
|
|||
#include "mozilla/dom/MessageEventBinding.h"
|
||||
#include "mozilla/dom/MessagePort.h"
|
||||
#include "mozilla/dom/MessagePortBinding.h"
|
||||
#include "mozilla/dom/nsCSPUtils.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/dom/PMessagePort.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
|
|
@ -549,7 +550,7 @@ private:
|
|||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (swm) {
|
||||
swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
|
||||
aWorkerPrivate->WorkerName(),
|
||||
aWorkerPrivate->ServiceWorkerScope(),
|
||||
aWorkerPrivate->ScriptURL(),
|
||||
EmptyString(), EmptyString(), EmptyString(),
|
||||
0, 0, JSREPORT_ERROR, JSEXN_ERR);
|
||||
|
|
@ -1254,7 +1255,7 @@ private:
|
|||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (swm) {
|
||||
swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
|
||||
aWorkerPrivate->WorkerName(),
|
||||
aWorkerPrivate->ServiceWorkerScope(),
|
||||
aWorkerPrivate->ScriptURL(),
|
||||
mReport.mMessage,
|
||||
mReport.mFilename, mReport.mLine, mReport.mLineNumber,
|
||||
|
|
@ -2382,6 +2383,56 @@ WorkerPrivateParent<Derived>::GetDocument() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
nsresult
|
||||
WorkerPrivateParent<Derived>::SetCSPFromHeaderValues(const nsACString& aCSPHeaderValue,
|
||||
const nsACString& aCSPReportOnlyHeaderValue)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mLoadInfo.mCSP);
|
||||
|
||||
NS_ConvertASCIItoUTF16 cspHeaderValue(aCSPHeaderValue);
|
||||
NS_ConvertASCIItoUTF16 cspROHeaderValue(aCSPReportOnlyHeaderValue);
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
nsresult rv = mLoadInfo.mPrincipal->EnsureCSP(nullptr, getter_AddRefs(csp));
|
||||
if (!csp) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If there's a CSP header, apply it.
|
||||
if (!cspHeaderValue.IsEmpty()) {
|
||||
rv = CSP_AppendCSPFromHeader(csp, cspHeaderValue, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
// If there's a report-only CSP header, apply it.
|
||||
if (!cspROHeaderValue.IsEmpty()) {
|
||||
rv = CSP_AppendCSPFromHeader(csp, cspROHeaderValue, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Set evalAllowed, default value is set in GetAllowsEval
|
||||
bool evalAllowed = false;
|
||||
bool reportEvalViolations = false;
|
||||
rv = csp->GetAllowsEval(&reportEvalViolations, &evalAllowed);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Set ReferrerPolicy, default value is set in GetReferrerPolicy
|
||||
bool hasReferrerPolicy = false;
|
||||
uint32_t rp = mozilla::net::RP_Unset;
|
||||
rv = csp->GetReferrerPolicy(&rp, &hasReferrerPolicy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mLoadInfo.mCSP = csp;
|
||||
mLoadInfo.mEvalAllowed = evalAllowed;
|
||||
mLoadInfo.mReportCSPViolations = reportEvalViolations;
|
||||
|
||||
if (hasReferrerPolicy) {
|
||||
mLoadInfo.mReferrerPolicy = static_cast<net::ReferrerPolicy>(rp);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Can't use NS_IMPL_CYCLE_COLLECTION_CLASS(WorkerPrivateParent) because of the
|
||||
// templates.
|
||||
|
|
@ -3628,47 +3679,53 @@ WorkerPrivateParent<Derived>::SetBaseURI(nsIURI* aBaseURI)
|
|||
nsContentUtils::GetUTFOrigin(aBaseURI, mLocationInfo.mOrigin);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
WorkerPrivateParent<Derived>::SetPrincipal(nsIPrincipal* aPrincipal,
|
||||
nsILoadGroup* aLoadGroup)
|
||||
nsresult
|
||||
WorkerLoadInfo::SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
|
||||
nsILoadGroup* aLoadGroup)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(aLoadGroup, aPrincipal));
|
||||
MOZ_ASSERT(!mLoadInfo.mPrincipalInfo);
|
||||
|
||||
mLoadInfo.mPrincipal = aPrincipal;
|
||||
mLoadInfo.mPrincipalIsSystem = nsContentUtils::IsSystemPrincipal(aPrincipal);
|
||||
mPrincipal = aPrincipal;
|
||||
mPrincipalIsSystem = nsContentUtils::IsSystemPrincipal(aPrincipal);
|
||||
|
||||
aPrincipal->GetCsp(getter_AddRefs(mLoadInfo.mCSP));
|
||||
nsresult rv = aPrincipal->GetCsp(getter_AddRefs(mCSP));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mLoadInfo.mCSP) {
|
||||
mLoadInfo.mCSP->GetAllowsEval(&mLoadInfo.mReportCSPViolations,
|
||||
&mLoadInfo.mEvalAllowed);
|
||||
if (mCSP) {
|
||||
mCSP->GetAllowsEval(&mReportCSPViolations, &mEvalAllowed);
|
||||
// Set ReferrerPolicy
|
||||
bool hasReferrerPolicy = false;
|
||||
uint32_t rp = mozilla::net::RP_Default;
|
||||
uint32_t rp = mozilla::net::RP_Unset;
|
||||
|
||||
nsresult rv = mLoadInfo.mCSP->GetReferrerPolicy(&rp, &hasReferrerPolicy);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
rv = mCSP->GetReferrerPolicy(&rp, &hasReferrerPolicy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (hasReferrerPolicy) {
|
||||
mLoadInfo.mReferrerPolicy = static_cast<net::ReferrerPolicy>(rp);
|
||||
mReferrerPolicy = static_cast<net::ReferrerPolicy>(rp);
|
||||
}
|
||||
} else {
|
||||
mLoadInfo.mEvalAllowed = true;
|
||||
mLoadInfo.mReportCSPViolations = false;
|
||||
mEvalAllowed = true;
|
||||
mReportCSPViolations = false;
|
||||
}
|
||||
|
||||
mLoadInfo.mLoadGroup = aLoadGroup;
|
||||
mLoadGroup = aLoadGroup;
|
||||
|
||||
mLoadInfo.mPrincipalInfo = new PrincipalInfo();
|
||||
mLoadInfo.mOriginAttributes = nsContentUtils::GetOriginAttributes(aLoadGroup);
|
||||
mPrincipalInfo = new PrincipalInfo();
|
||||
mOriginAttributes = nsContentUtils::GetOriginAttributes(aLoadGroup);
|
||||
|
||||
nsContentUtils::GetUTFOrigin(aPrincipal, mLoadInfo.mOrigin);
|
||||
rv = PrincipalToPrincipalInfo(aPrincipal, mPrincipalInfo);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
PrincipalToPrincipalInfo(aPrincipal, mLoadInfo.mPrincipalInfo));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
nsresult
|
||||
WorkerPrivateParent<Derived>::SetPrincipalOnMainThread(nsIPrincipal* aPrincipal,
|
||||
nsILoadGroup* aLoadGroup)
|
||||
{
|
||||
return mLoadInfo.SetPrincipalOnMainThread(aPrincipal, aLoadGroup);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
|
|
@ -6679,7 +6736,7 @@ WorkerPrivate::GetOrCreateGlobalScope(JSContext* aCx)
|
|||
if (IsSharedWorker()) {
|
||||
globalScope = new SharedWorkerGlobalScope(this, WorkerName());
|
||||
} else if (IsServiceWorker()) {
|
||||
globalScope = new ServiceWorkerGlobalScope(this, WorkerName());
|
||||
globalScope = new ServiceWorkerGlobalScope(this, ServiceWorkerScope());
|
||||
} else {
|
||||
globalScope = new DedicatedWorkerGlobalScope(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#ifndef mozilla_dom_workers_workerprivate_h__
|
||||
#define mozilla_dom_workers_workerprivate_h__
|
||||
|
||||
#include "Workers.h"
|
||||
#include "mozilla/dom/workers/Workers.h"
|
||||
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
|
|
@ -34,8 +34,8 @@
|
|||
#include "nsThreadUtils.h"
|
||||
#include "nsTObserverArray.h"
|
||||
|
||||
#include "Queue.h"
|
||||
#include "WorkerHolder.h"
|
||||
#include "mozilla/dom/workerinternals/Queue.h"
|
||||
#include "mozilla/dom/workers/bindings/WorkerHolder.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#undef PostMessage
|
||||
|
|
@ -535,6 +535,13 @@ public:
|
|||
return mLoadInfo.mServiceWorkerID;
|
||||
}
|
||||
|
||||
const nsCString&
|
||||
ServiceWorkerScope() const
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
|
||||
return mWorkerName;
|
||||
}
|
||||
|
||||
nsIURI*
|
||||
GetBaseURI() const
|
||||
{
|
||||
|
|
@ -656,8 +663,8 @@ public:
|
|||
return mLoadInfo.mPrincipal;
|
||||
}
|
||||
|
||||
void
|
||||
SetPrincipal(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup);
|
||||
nsresult
|
||||
SetPrincipalOnMainThread(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup);
|
||||
|
||||
bool
|
||||
UsesSystemPrincipal() const
|
||||
|
|
@ -701,6 +708,10 @@ public:
|
|||
mLoadInfo.mCSP = aCSP;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SetCSPFromHeaderValues(const nsACString& aCSPHeaderValue,
|
||||
const nsACString& aCSPReportOnlyHeaderValue);
|
||||
|
||||
net::ReferrerPolicy
|
||||
GetReferrerPolicy() const
|
||||
{
|
||||
|
|
@ -827,7 +838,7 @@ public:
|
|||
const nsCString&
|
||||
WorkerName() const
|
||||
{
|
||||
MOZ_ASSERT(IsServiceWorker() || IsSharedWorker());
|
||||
MOZ_ASSERT(IsSharedWorker());
|
||||
return mWorkerName;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@
|
|||
#ifndef mozilla_dom_workers_workerrunnable_h__
|
||||
#define mozilla_dom_workers_workerrunnable_h__
|
||||
|
||||
#include "Workers.h"
|
||||
#include "mozilla/dom/workers/Workers.h"
|
||||
|
||||
#include "nsICancelableRunnable.h"
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsThreadUtils.h" /* nsRunnable */
|
||||
#include "WorkerHolder.h"
|
||||
#include "mozilla/dom/workers/bindings/WorkerHolder.h"
|
||||
|
||||
struct JSContext;
|
||||
class nsIEventTarget;
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ NS_CreateJSTimeoutHandler(JSContext* aCx,
|
|||
extern already_AddRefed<nsIScriptTimeoutHandler>
|
||||
NS_CreateJSTimeoutHandler(JSContext* aCx,
|
||||
mozilla::dom::workers::WorkerPrivate* aWorkerPrivate,
|
||||
const nsAString& aExpression);
|
||||
const nsAString& aExpression,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
|
@ -268,7 +269,7 @@ WorkerGlobalScope::SetTimeout(JSContext* aCx,
|
|||
|
||||
nsCOMPtr<nsIScriptTimeoutHandler> handler =
|
||||
NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler, aArguments, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
if (!handler) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -285,7 +286,11 @@ WorkerGlobalScope::SetTimeout(JSContext* aCx,
|
|||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsCOMPtr<nsIScriptTimeoutHandler> handler =
|
||||
NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler);
|
||||
NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler, aRv);
|
||||
if (!handler) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mWorkerPrivate->SetTimeout(aCx, handler, aTimeout, false, aRv);
|
||||
}
|
||||
|
||||
|
|
@ -326,7 +331,10 @@ WorkerGlobalScope::SetInterval(JSContext* aCx,
|
|||
Sequence<JS::Value> dummy;
|
||||
|
||||
nsCOMPtr<nsIScriptTimeoutHandler> handler =
|
||||
NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler);
|
||||
NS_CreateJSTimeoutHandler(aCx, mWorkerPrivate, aHandler, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return 0;
|
||||
}
|
||||
return mWorkerPrivate->SetTimeout(aCx, handler, aTimeout, true, aRv);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -268,6 +268,8 @@ struct WorkerLoadInfo
|
|||
~WorkerLoadInfo();
|
||||
|
||||
void StealFrom(WorkerLoadInfo& aOther);
|
||||
|
||||
nsresult SetPrincipalOnMainThread(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup);
|
||||
};
|
||||
|
||||
// All of these are implemented in RuntimeService.cpp
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@ EXPORTS.mozilla.dom += [
|
|||
'WorkerScope.h',
|
||||
]
|
||||
|
||||
# Private stuff.
|
||||
EXPORTS.mozilla.dom.workerinternals += [
|
||||
'Queue.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.dom.workers += [
|
||||
'RuntimeService.h',
|
||||
'ServiceWorkerCommon.h',
|
||||
|
|
|
|||
|
|
@ -248,10 +248,11 @@ NS_IMETHODIMP
|
|||
nsXBLContentSink::HandleStartElement(const char16_t *aName,
|
||||
const char16_t **aAtts,
|
||||
uint32_t aAttsCount,
|
||||
uint32_t aLineNumber)
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber)
|
||||
{
|
||||
nsresult rv = nsXMLContentSink::HandleStartElement(aName, aAtts, aAttsCount,
|
||||
aLineNumber);
|
||||
aLineNumber, aColumnNumber);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
|
@ -850,7 +851,8 @@ nsXBLContentSink::ConstructParameter(const char16_t **aAtts)
|
|||
|
||||
nsresult
|
||||
nsXBLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
|
||||
mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
|
||||
mozilla::dom::NodeInfo* aNodeInfo,
|
||||
uint32_t aLineNumber, uint32_t aColumnNumber,
|
||||
nsIContent** aResult, bool* aAppendContent,
|
||||
FromParser aFromParser)
|
||||
{
|
||||
|
|
@ -858,7 +860,7 @@ nsXBLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
|
|||
if (!aNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) {
|
||||
#endif
|
||||
return nsXMLContentSink::CreateElement(aAtts, aAttsCount, aNodeInfo,
|
||||
aLineNumber, aResult,
|
||||
aLineNumber, aColumnNumber, aResult,
|
||||
aAppendContent, aFromParser);
|
||||
#ifdef MOZ_XUL
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,8 @@ public:
|
|||
NS_IMETHOD HandleStartElement(const char16_t *aName,
|
||||
const char16_t **aAtts,
|
||||
uint32_t aAttsCount,
|
||||
uint32_t aLineNumber) override;
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber) override;
|
||||
|
||||
NS_IMETHOD HandleEndElement(const char16_t *aName) override;
|
||||
|
||||
|
|
@ -89,7 +90,8 @@ protected:
|
|||
bool NotifyForDocElement() override { return false; }
|
||||
|
||||
nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
|
||||
mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
|
||||
mozilla::dom::NodeInfo* aNodeInfo,
|
||||
uint32_t aLineNumber, uint32_t aColumnNumber,
|
||||
nsIContent** aResult, bool* aAppendContent,
|
||||
mozilla::dom::FromParser aFromParser) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -446,7 +446,8 @@ nsXMLContentSink::SetParser(nsParserBase* aParser)
|
|||
|
||||
nsresult
|
||||
nsXMLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
|
||||
mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
|
||||
mozilla::dom::NodeInfo* aNodeInfo,
|
||||
uint32_t aLineNumber, uint32_t aColumnNumber,
|
||||
nsIContent** aResult, bool* aAppendContent,
|
||||
FromParser aFromParser)
|
||||
{
|
||||
|
|
@ -466,6 +467,7 @@ nsXMLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
|
|||
) {
|
||||
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(content);
|
||||
sele->SetScriptLineNumber(aLineNumber);
|
||||
sele->SetScriptColumnNumber(aColumnNumber);
|
||||
sele->SetCreatorParser(GetParser());
|
||||
}
|
||||
|
||||
|
|
@ -500,6 +502,7 @@ nsXMLContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
|
|||
}
|
||||
if (!aNodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML)) {
|
||||
ssle->SetLineNumber(aFromParser ? aLineNumber : 0);
|
||||
ssle->SetColumnNumber(aFromParser ? aColumnNumber : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -918,10 +921,11 @@ NS_IMETHODIMP
|
|||
nsXMLContentSink::HandleStartElement(const char16_t *aName,
|
||||
const char16_t **aAtts,
|
||||
uint32_t aAttsCount,
|
||||
uint32_t aLineNumber)
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber)
|
||||
{
|
||||
return HandleStartElement(aName, aAtts, aAttsCount, aLineNumber,
|
||||
true);
|
||||
aColumnNumber, true);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
@ -929,6 +933,7 @@ nsXMLContentSink::HandleStartElement(const char16_t *aName,
|
|||
const char16_t **aAtts,
|
||||
uint32_t aAttsCount,
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber,
|
||||
bool aInterruptable)
|
||||
{
|
||||
NS_PRECONDITION(aAttsCount % 2 == 0, "incorrect aAttsCount");
|
||||
|
|
@ -963,7 +968,7 @@ nsXMLContentSink::HandleStartElement(const char16_t *aName,
|
|||
nsIDOMNode::ELEMENT_NODE);
|
||||
|
||||
result = CreateElement(aAtts, aAttsCount, nodeInfo, aLineNumber,
|
||||
getter_AddRefs(content), &appendContent,
|
||||
aColumnNumber, getter_AddRefs(content), &appendContent,
|
||||
FROM_PARSER_NETWORK);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
|
||||
|
|
|
|||
|
|
@ -114,7 +114,8 @@ protected:
|
|||
nsIContent *aContent);
|
||||
virtual bool NotifyForDocElement() { return true; }
|
||||
virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
|
||||
mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
|
||||
mozilla::dom::NodeInfo* aNodeInfo,
|
||||
uint32_t aLineNumber, uint32_t aColumnNumber,
|
||||
nsIContent** aResult, bool* aAppendContent,
|
||||
mozilla::dom::FromParser aFromParser);
|
||||
|
||||
|
|
@ -161,7 +162,7 @@ protected:
|
|||
|
||||
nsresult HandleStartElement(const char16_t *aName, const char16_t **aAtts,
|
||||
uint32_t aAttsCount, uint32_t aLineNumber,
|
||||
bool aInterruptable);
|
||||
uint32_t aColumnNumber, bool aInterruptable);
|
||||
nsresult HandleEndElement(const char16_t *aName, bool aInterruptable);
|
||||
nsresult HandleCharacterData(const char16_t *aData, uint32_t aLength,
|
||||
bool aInterruptable);
|
||||
|
|
|
|||
|
|
@ -83,7 +83,8 @@ protected:
|
|||
nsIAtom* aTagName,
|
||||
nsIContent* aContent) override;
|
||||
virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
|
||||
mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
|
||||
mozilla::dom::NodeInfo* aNodeInfo,
|
||||
uint32_t aLineNumber, uint32_t aColumnNumber,
|
||||
nsIContent** aResult, bool* aAppendContent,
|
||||
mozilla::dom::FromParser aFromParser) override;
|
||||
virtual nsresult CloseElement(nsIContent* aContent) override;
|
||||
|
|
@ -199,7 +200,8 @@ nsXMLFragmentContentSink::SetDocElement(int32_t aNameSpaceID,
|
|||
|
||||
nsresult
|
||||
nsXMLFragmentContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
|
||||
mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
|
||||
mozilla::dom::NodeInfo* aNodeInfo,
|
||||
uint32_t aLineNumber, uint32_t aColumnNumber,
|
||||
nsIContent** aResult, bool* aAppendContent,
|
||||
FromParser /*aFromParser*/)
|
||||
{
|
||||
|
|
@ -207,6 +209,7 @@ nsXMLFragmentContentSink::CreateElement(const char16_t** aAtts, uint32_t aAttsCo
|
|||
// fancy CloseElement stuff.
|
||||
nsresult rv = nsXMLContentSink::CreateElement(aAtts, aAttsCount,
|
||||
aNodeInfo, aLineNumber,
|
||||
aColumnNumber,
|
||||
aResult, aAppendContent,
|
||||
NOT_FROM_PARSER);
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,8 @@ NS_IMETHODIMP
|
|||
txStylesheetSink::HandleStartElement(const char16_t *aName,
|
||||
const char16_t **aAtts,
|
||||
uint32_t aAttsCount,
|
||||
uint32_t aLineNumber)
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber)
|
||||
{
|
||||
NS_PRECONDITION(aAttsCount % 2 == 0, "incorrect aAttsCount");
|
||||
|
||||
|
|
|
|||
|
|
@ -437,7 +437,8 @@ NS_IMETHODIMP
|
|||
XULContentSinkImpl::HandleStartElement(const char16_t *aName,
|
||||
const char16_t **aAtts,
|
||||
uint32_t aAttsCount,
|
||||
uint32_t aLineNumber)
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber)
|
||||
{
|
||||
// XXX Hopefully the parser will flag this before we get here. If
|
||||
// we're in the epilog, there should be no new elements
|
||||
|
|
@ -694,7 +695,7 @@ XULContentSinkImpl::ReportError(const char16_t* aErrorText,
|
|||
parsererror.Append((char16_t)0xFFFF);
|
||||
parsererror.AppendLiteral("parsererror");
|
||||
|
||||
rv = HandleStartElement(parsererror.get(), noAtts, 0, 0);
|
||||
rv = HandleStartElement(parsererror.get(), noAtts, 0, 0, 0);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = HandleCharacterData(aErrorText, NS_strlen(aErrorText));
|
||||
|
|
@ -704,7 +705,7 @@ XULContentSinkImpl::ReportError(const char16_t* aErrorText,
|
|||
sourcetext.Append((char16_t)0xFFFF);
|
||||
sourcetext.AppendLiteral("sourcetext");
|
||||
|
||||
rv = HandleStartElement(sourcetext.get(), noAtts, 0, 0);
|
||||
rv = HandleStartElement(sourcetext.get(), noAtts, 0, 0, 0);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = HandleCharacterData(aSourceText, NS_strlen(aSourceText));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue