Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
roytam1 2024-01-11 09:52:46 +08:00
commit 80c4f1d745
79 changed files with 1353 additions and 509 deletions

View file

@ -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>";
}

View file

@ -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:

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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,

View file

@ -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();
}

View file

@ -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()->

View file

@ -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___ */

View file

@ -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;

View file

@ -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

View file

@ -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");
}

View file

@ -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);

View file

@ -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 */

View file

@ -710,7 +710,7 @@ WorkerFetchResolver::FlushConsoleReport()
return;
}
swm->FlushReportsToAllClients(worker->WorkerName(), mReporter);
swm->FlushReportsToAllClients(worker->ServiceWorkerScope(), mReporter);
return;
}

View file

@ -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.

View file

@ -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
{

View file

@ -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;

View file

@ -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:

View file

@ -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);

View file

@ -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

View file

@ -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.

View file

@ -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’

View file

@ -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”)

View file

@ -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;
}
}

View file

@ -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.
*/

View 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;
}

View 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

View file

@ -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',
]

View file

@ -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;
}

View file

@ -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

View file

@ -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) {

View file

@ -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!");

View file

@ -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;

View file

@ -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;
}

View file

@ -16,6 +16,7 @@ dictionary CSPReportProperties {
DOMString source-file;
DOMString script-sample;
long line-number;
long column-number;
};
dictionary CSPReport {

View 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;
};

View file

@ -694,6 +694,7 @@ GENERATED_EVENTS_WEBIDL_FILES = [
'PromiseRejectionEvent.webidl',
'RecordErrorEvent.webidl',
'ScrollViewChangeEvent.webidl',
'SecurityPolicyViolationEvent.webidl',
'ServiceWorkerMessageEvent.webidl',
'StyleRuleChangeEvent.webidl',
'StyleSheetApplicableStateChangeEvent.webidl',

View file

@ -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"

View file

@ -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());
}
}

View file

@ -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

View file

@ -805,7 +805,7 @@ public:
WaitUntilHandler(WorkerPrivate* aWorkerPrivate, JSContext* aCx)
: mWorkerPrivate(aWorkerPrivate)
, mScope(mWorkerPrivate->WorkerName())
, mScope(mWorkerPrivate->ServiceWorkerScope())
, mLine(0)
, mColumn(0)
{

View file

@ -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);

View file

@ -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;

View file

@ -52,6 +52,11 @@ ServiceWorkerRegisterJob::AsyncExecute()
}
} else {
registration = swm->CreateNewRegistration(mScope, mPrincipal);
if (!registration) {
FailUpdateJob(NS_ERROR_DOM_ABORT_ERR);
return;
}
}
SetRegistration(registration);

View file

@ -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);

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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

View file

@ -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',

View file

@ -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
}

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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");

View file

@ -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));