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

This commit is contained in:
roytam1 2022-11-25 11:46:08 +08:00
commit de0b4ac202
15 changed files with 437 additions and 77 deletions

View file

@ -7058,16 +7058,26 @@ nsContentUtils::HasDistributedChildren(nsIContent* aContent)
// static // static
bool bool
nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader) nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader,
const nsACString& aValue)
{ {
if (IsForbiddenSystemRequestHeader(aHeader)) { if (IsForbiddenSystemRequestHeader(aHeader)) {
return true; return true;
} }
if ((nsContentUtils::IsOverrideMethodHeader(aHeader) &&
nsContentUtils::ContainsForbiddenMethod(aValue))) {
return true;
}
return StringBeginsWith(aHeader, NS_LITERAL_CSTRING("proxy-"), if (StringBeginsWith(aHeader, NS_LITERAL_CSTRING("proxy-"),
nsCaseInsensitiveCStringComparator()) || nsCaseInsensitiveCStringComparator()) ||
StringBeginsWith(aHeader, NS_LITERAL_CSTRING("sec-"), StringBeginsWith(aHeader, NS_LITERAL_CSTRING("sec-"),
nsCaseInsensitiveCStringComparator()); nsCaseInsensitiveCStringComparator())) {
return true;
}
return false;
} }
// static // static
@ -7096,6 +7106,64 @@ nsContentUtils::IsForbiddenResponseHeader(const nsACString& aHeader)
aHeader.LowerCaseEqualsASCII("set-cookie2")); aHeader.LowerCaseEqualsASCII("set-cookie2"));
} }
// static
bool
nsContentUtils::IsOverrideMethodHeader(const nsACString& headerName) {
return headerName.LowerCaseEqualsASCII("x-http-method-override") ||
headerName.LowerCaseEqualsASCII("x-http-method") ||
headerName.LowerCaseEqualsASCII("x-method-override");
}
// static
bool
nsContentUtils::ContainsForbiddenMethod(const nsACString& headerValue) {
bool hasInsecureMethod = false;
nsCCharSeparatedTokenizer tokenizer(headerValue, ',');
while (tokenizer.hasMoreTokens()) {
const nsDependentCSubstring& value = tokenizer.nextToken();
if (value.LowerCaseEqualsASCII("connect") ||
value.LowerCaseEqualsASCII("trace") ||
value.LowerCaseEqualsASCII("track")) {
hasInsecureMethod = true;
break;
}
}
return hasInsecureMethod;
}
// static
bool nsContentUtils::IsCorsUnsafeRequestHeaderValue(
const nsACString& aHeaderValue) {
const char* cur = aHeaderValue.BeginReading();
const char* end = aHeaderValue.EndReading();
while (cur != end) {
// Implementation of
// https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte Is less
// than a space but not a horizontal tab
if ((*cur < ' ' && *cur != '\t') || *cur == '"' || *cur == '(' ||
*cur == ')' || *cur == ':' || *cur == '<' || *cur == '>' ||
*cur == '?' || *cur == '@' || *cur == '[' || *cur == '\\' ||
*cur == ']' || *cur == '{' || *cur == '}' ||
*cur == 0x7F) { // 0x75 is DEL
return true;
}
cur++;
}
return false;
}
// static
bool nsContentUtils::IsAllowedNonCorsAccept(const nsACString& aHeaderValue) {
if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
return false;
}
return true;
}
// static // static
bool bool
nsContentUtils::IsAllowedNonCorsContentType(const nsACString& aHeaderValue) nsContentUtils::IsAllowedNonCorsContentType(const nsACString& aHeaderValue)
@ -7103,6 +7171,10 @@ nsContentUtils::IsAllowedNonCorsContentType(const nsACString& aHeaderValue)
nsAutoCString contentType; nsAutoCString contentType;
nsAutoCString unused; nsAutoCString unused;
if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
return false;
}
nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused); nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return false; return false;
@ -7113,6 +7185,41 @@ nsContentUtils::IsAllowedNonCorsContentType(const nsACString& aHeaderValue)
contentType.LowerCaseEqualsLiteral("multipart/form-data"); contentType.LowerCaseEqualsLiteral("multipart/form-data");
} }
// static
bool nsContentUtils::IsAllowedNonCorsLanguage(const nsACString& aHeaderValue) {
const char* cur = aHeaderValue.BeginReading();
const char* end = aHeaderValue.EndReading();
while (cur != end) {
if ((*cur >= '0' && *cur <= '9') || (*cur >= 'A' && *cur <= 'Z') ||
(*cur >= 'a' && *cur <= 'z') || *cur == ' ' || *cur == '*' ||
*cur == ',' || *cur == '-' || *cur == '.' || *cur == ';' ||
*cur == '=') {
cur++;
continue;
}
return false;
}
return true;
}
// static
bool nsContentUtils::IsCORSSafelistedRequestHeader(const nsACString& aName,
const nsACString& aValue) {
// See https://fetch.spec.whatwg.org/#cors-safelisted-request-header
if (aValue.Length() > 128) {
return false;
}
return (aName.LowerCaseEqualsLiteral("accept") &&
nsContentUtils::IsAllowedNonCorsAccept(aValue)) ||
(aName.LowerCaseEqualsLiteral("accept-language") &&
nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
(aName.LowerCaseEqualsLiteral("content-language") &&
nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
(aName.LowerCaseEqualsLiteral("content-type") &&
nsContentUtils::IsAllowedNonCorsContentType(aValue));
}
bool bool
nsContentUtils::DOMWindowDumpEnabled() nsContentUtils::DOMWindowDumpEnabled()
{ {

View file

@ -2425,7 +2425,8 @@ public:
* Returns whether a given header is forbidden for an XHR or fetch * Returns whether a given header is forbidden for an XHR or fetch
* request. * request.
*/ */
static bool IsForbiddenRequestHeader(const nsACString& aHeader); static bool IsForbiddenRequestHeader(const nsACString& aHeader,
const nsACString& aValue);
/** /**
* Returns whether a given header is forbidden for a system XHR * Returns whether a given header is forbidden for a system XHR
@ -2433,18 +2434,50 @@ public:
*/ */
static bool IsForbiddenSystemRequestHeader(const nsACString& aHeader); static bool IsForbiddenSystemRequestHeader(const nsACString& aHeader);
/**
* Returns whether a given header has characters that aren't permitted
*/
static bool IsCorsUnsafeRequestHeaderValue(const nsACString& aHeaderValue);
/**
* Returns whether a given Accept header value is allowed
* for a non-CORS XHR or fetch request.
*/
static bool IsAllowedNonCorsAccept(const nsACString& aHeaderValue);
/** /**
* Returns whether a given Content-Type header value is allowed * Returns whether a given Content-Type header value is allowed
* for a non-CORS XHR or fetch request. * for a non-CORS XHR or fetch request.
*/ */
static bool IsAllowedNonCorsContentType(const nsACString& aHeaderValue); static bool IsAllowedNonCorsContentType(const nsACString& aHeaderValue);
/**
* Returns whether a given Content-Language or accept-language header value is
* allowed for a non-CORS XHR or fetch request.
*/
static bool IsAllowedNonCorsLanguage(const nsACString& aHeaderValue);
/**
* Returns whether a given header and value is a CORS-safelisted request
* header per https://fetch.spec.whatwg.org/#cors-safelisted-request-header
*/
static bool IsCORSSafelistedRequestHeader(const nsACString& aName,
const nsACString& aValue);
/** /**
* Returns whether a given header is forbidden for an XHR or fetch * Returns whether a given header is forbidden for an XHR or fetch
* response. * response.
*/ */
static bool IsForbiddenResponseHeader(const nsACString& aHeader); static bool IsForbiddenResponseHeader(const nsACString& aHeader);
/**
* Checks whether the header overrides any http methods
*/
static bool IsOverrideMethodHeader(const nsACString& headerName);
/**
* Checks whether the header value contains any forbidden method
*/
static bool ContainsForbiddenMethod(const nsACString& headerValue);
/** /**
* Returns the inner window ID for the window associated with a request, * Returns the inner window ID for the window associated with a request,
*/ */

View file

@ -5,6 +5,7 @@
#include "mozilla/dom/InternalHeaders.h" #include "mozilla/dom/InternalHeaders.h"
#include "FetchUtil.h"
#include "mozilla/dom/FetchTypes.h" #include "mozilla/dom/FetchTypes.h"
#include "mozilla/ErrorResult.h" #include "mozilla/ErrorResult.h"
@ -46,20 +47,112 @@ InternalHeaders::ToIPC(nsTArray<HeadersEntry>& aIPCHeaders,
} }
} }
bool
InternalHeaders::IsValidHeaderValue(const nsCString& aLowerName,
const nsCString& aNormalizedValue,
ErrorResult& aRv) {
// Steps 2 to 6 for ::Set() and ::Append() in the spec.
// Step 2
if (IsInvalidName(aLowerName, aRv) || IsInvalidValue(aNormalizedValue, aRv)) {
return false;
}
// Step 3
if (IsImmutable(aRv)) {
return false;
}
// Step 4
if (mGuard == HeadersGuardEnum::Request) {
if (IsForbiddenRequestHeader(aLowerName, aNormalizedValue)) {
return false;
}
}
// Step 5
if (mGuard == HeadersGuardEnum::Request_no_cors) {
nsAutoCString tempValue;
Get(aLowerName, tempValue, aRv);
if (tempValue.IsVoid()) {
tempValue = aNormalizedValue;
} else {
tempValue.Append(", ");
tempValue.Append(aNormalizedValue);
}
if (!nsContentUtils::IsCORSSafelistedRequestHeader(aLowerName, tempValue)) {
return false;
}
}
// Step 6
else if (IsForbiddenResponseHeader(aLowerName)) {
return false;
}
return true;
}
void void
InternalHeaders::Append(const nsACString& aName, const nsACString& aValue, InternalHeaders::Append(const nsACString& aName, const nsACString& aValue,
ErrorResult& aRv) ErrorResult& aRv)
{ {
// Step 1
nsAutoCString trimValue;
NS_TrimHTTPWhitespace(aValue, trimValue);
// Steps 2 to 6
nsAutoCString lowerName; nsAutoCString lowerName;
ToLowerCase(aName, lowerName); ToLowerCase(aName, lowerName);
if (!IsValidHeaderValue(lowerName, trimValue, aRv)) {
if (IsInvalidMutableHeader(lowerName, aValue, aRv)) {
return; return;
} }
// Step 7
SetListDirty(); SetListDirty();
mList.AppendElement(Entry(lowerName, aValue)); mList.AppendElement(Entry(lowerName, aValue));
// Step 8
if (mGuard == HeadersGuardEnum::Request_no_cors) {
RemovePrivilegedNoCorsRequestHeaders();
}
}
void InternalHeaders::RemovePrivilegedNoCorsRequestHeaders() {
bool dirty = false;
// remove in reverse order to minimize copying
for (int32_t i = mList.Length() - 1; i >= 0; --i) {
if (IsPrivilegedNoCorsRequestHeaderName(mList[i].mName)) {
mList.RemoveElementAt(i);
dirty = true;
}
}
if (dirty) {
SetListDirty();
}
}
bool InternalHeaders::DeleteInternal(const nsCString& aLowerName,
ErrorResult& aRv) {
bool dirty = false;
// remove in reverse order to minimize copying
for (int32_t i = mList.Length() - 1; i >= 0; --i) {
if (mList[i].mName.EqualsIgnoreCase(aLowerName.get())) {
mList.RemoveElementAt(i);
dirty = true;
}
}
if (dirty) {
SetListDirty();
}
return dirty;
} }
void void
@ -68,17 +161,43 @@ InternalHeaders::Delete(const nsACString& aName, ErrorResult& aRv)
nsAutoCString lowerName; nsAutoCString lowerName;
ToLowerCase(aName, lowerName); ToLowerCase(aName, lowerName);
if (IsInvalidMutableHeader(lowerName, aRv)) { // Step 1
if (IsInvalidName(lowerName, aRv)) {
return; return;
} }
SetListDirty(); // Step 2
if (IsImmutable(aRv)) {
return;
}
// remove in reverse order to minimize copying // Step 3
for (int32_t i = mList.Length() - 1; i >= 0; --i) { nsAutoCString value;
if (lowerName == mList[i].mName) { GetInternal(lowerName, value, aRv);
mList.RemoveElementAt(i); if (IsForbiddenRequestHeader(lowerName, value)) {
} return;
}
// Step 4
if (mGuard == HeadersGuardEnum::Request_no_cors &&
!IsNoCorsSafelistedRequestHeaderName(lowerName) &&
!IsPrivilegedNoCorsRequestHeaderName(lowerName)) {
return;
}
// Step 5
if (IsForbiddenResponseHeader(lowerName)) {
return;
}
// Steps 6 and 7
if (!DeleteInternal(lowerName, aRv)) {
return;
}
// Step 8
if (mGuard == HeadersGuardEnum::Request_no_cors) {
RemovePrivilegedNoCorsRequestHeaders();
} }
} }
@ -91,12 +210,18 @@ InternalHeaders::Get(const nsACString& aName, nsACString& aValue, ErrorResult& a
if (IsInvalidName(lowerName, aRv)) { if (IsInvalidName(lowerName, aRv)) {
return; return;
} }
GetInternal(lowerName, aValue, aRv);
}
void
InternalHeaders::GetInternal(const nsCString& aLowerName,
nsACString& aValue,
ErrorResult& aRv) const {
const char* delimiter = ","; const char* delimiter = ",";
bool firstValueFound = false; bool firstValueFound = false;
for (uint32_t i = 0; i < mList.Length(); ++i) { for (uint32_t i = 0; i < mList.Length(); ++i) {
if (lowerName == mList[i].mName) { if (aLowerName == mList[i].mName) {
if (firstValueFound) { if (firstValueFound) {
aValue += delimiter; aValue += delimiter;
} }
@ -153,13 +278,18 @@ InternalHeaders::Has(const nsACString& aName, ErrorResult& aRv) const
void void
InternalHeaders::Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv) InternalHeaders::Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv)
{ {
// Step 1
nsAutoCString trimValue;
NS_TrimHTTPWhitespace(aValue, trimValue);
// Steps 2 to 6
nsAutoCString lowerName; nsAutoCString lowerName;
ToLowerCase(aName, lowerName); ToLowerCase(aName, lowerName);
if (!IsValidHeaderValue(lowerName, trimValue, aRv)) {
if (IsInvalidMutableHeader(lowerName, aValue, aRv)) {
return; return;
} }
// Step 7
SetListDirty(); SetListDirty();
int32_t firstIndex = INT32_MAX; int32_t firstIndex = INT32_MAX;
@ -179,6 +309,11 @@ InternalHeaders::Set(const nsACString& aName, const nsACString& aValue, ErrorRes
} else { } else {
mList.AppendElement(Entry(lowerName, aValue)); mList.AppendElement(Entry(lowerName, aValue));
} }
// Step 8
if (mGuard == HeadersGuardEnum::Request_no_cors) {
RemovePrivilegedNoCorsRequestHeaders();
}
} }
void void
@ -200,6 +335,22 @@ InternalHeaders::~InternalHeaders()
{ {
} }
// static
bool
InternalHeaders::IsNoCorsSafelistedRequestHeaderName(const nsCString& aName) {
return aName.EqualsIgnoreCase("accept") ||
aName.EqualsIgnoreCase("accept-language") ||
aName.EqualsIgnoreCase("content-language") ||
aName.EqualsIgnoreCase("content-type");
}
// static
bool
InternalHeaders::IsPrivilegedNoCorsRequestHeaderName(
const nsCString& aName) {
return aName.EqualsIgnoreCase("range");
}
// static // static
bool bool
InternalHeaders::IsSimpleHeader(const nsACString& aName, const nsACString& aValue) InternalHeaders::IsSimpleHeader(const nsACString& aName, const nsACString& aValue)
@ -207,9 +358,12 @@ InternalHeaders::IsSimpleHeader(const nsACString& aName, const nsACString& aValu
// Note, we must allow a null content-type value here to support // Note, we must allow a null content-type value here to support
// get("content-type"), but the IsInvalidValue() check will prevent null // get("content-type"), but the IsInvalidValue() check will prevent null
// from being set or appended. // from being set or appended.
return aName.EqualsLiteral("accept") || return (aName.EqualsLiteral("accept") &&
aName.EqualsLiteral("accept-language") || nsContentUtils::IsAllowedNonCorsAccept(aValue)) ||
aName.EqualsLiteral("content-language") || (aName.EqualsLiteral("accept-language") &&
nsContentUtils::IsAllowedNonCorsLanguage(aValue))||
(aName.EqualsLiteral("content-language") &&
nsContentUtils::IsAllowedNonCorsLanguage(aValue))||
(aName.EqualsLiteral("content-type") && (aName.EqualsLiteral("content-type") &&
nsContentUtils::IsAllowedNonCorsContentType(aValue)); nsContentUtils::IsAllowedNonCorsContentType(aValue));
} }
@ -261,10 +415,11 @@ InternalHeaders::IsImmutable(ErrorResult& aRv) const
} }
bool bool
InternalHeaders::IsForbiddenRequestHeader(const nsACString& aName) const InternalHeaders::IsForbiddenRequestHeader(const nsACString& aName,
const nsACString& aValue) const
{ {
return mGuard == HeadersGuardEnum::Request && return mGuard == HeadersGuardEnum::Request &&
nsContentUtils::IsForbiddenRequestHeader(aName); nsContentUtils::IsForbiddenRequestHeader(aName, aValue);
} }
bool bool
@ -370,7 +525,7 @@ InternalHeaders::CORSHeaders(InternalHeaders* aHeaders, RequestCredentials aCred
ErrorResult result; ErrorResult result;
nsAutoCString acExposedNames; nsAutoCString acExposedNames;
aHeaders->GetFirst(NS_LITERAL_CSTRING("Access-Control-Expose-Headers"), acExposedNames, result); aHeaders->Get(NS_LITERAL_CSTRING("Access-Control-Expose-Headers"), acExposedNames, result);
MOZ_ASSERT(!result.Failed()); MOZ_ASSERT(!result.Failed());
bool allowAllHeaders = false; bool allowAllHeaders = false;

View file

@ -136,8 +136,11 @@ private:
static bool IsInvalidName(const nsACString& aName, ErrorResult& aRv); static bool IsInvalidName(const nsACString& aName, ErrorResult& aRv);
static bool IsInvalidValue(const nsACString& aValue, ErrorResult& aRv); static bool IsInvalidValue(const nsACString& aValue, ErrorResult& aRv);
bool IsValidHeaderValue(const nsCString& aLowerName,
const nsCString& aNormalizedValue, ErrorResult& aRv);
bool IsImmutable(ErrorResult& aRv) const; bool IsImmutable(ErrorResult& aRv) const;
bool IsForbiddenRequestHeader(const nsACString& aName) const; bool IsForbiddenRequestHeader(const nsACString& aName,
const nsACString& aValue) const;
bool IsForbiddenRequestNoCorsHeader(const nsACString& aName) const; bool IsForbiddenRequestNoCorsHeader(const nsACString& aName) const;
bool IsForbiddenRequestNoCorsHeader(const nsACString& aName, bool IsForbiddenRequestNoCorsHeader(const nsACString& aName,
const nsACString& aValue) const; const nsACString& aValue) const;
@ -156,11 +159,22 @@ private:
return IsInvalidName(aName, aRv) || return IsInvalidName(aName, aRv) ||
IsInvalidValue(aValue, aRv) || IsInvalidValue(aValue, aRv) ||
IsImmutable(aRv) || IsImmutable(aRv) ||
IsForbiddenRequestHeader(aName) || IsForbiddenRequestHeader(aName, aValue) ||
IsForbiddenRequestNoCorsHeader(aName, aValue) || IsForbiddenRequestNoCorsHeader(aName, aValue) ||
IsForbiddenResponseHeader(aName); IsForbiddenResponseHeader(aName);
} }
void RemovePrivilegedNoCorsRequestHeaders();
void GetInternal(const nsCString& aLowerName, nsACString& aValue,
ErrorResult& aRv) const;
bool DeleteInternal(const nsCString& aLowerName, ErrorResult& aRv);
static bool IsNoCorsSafelistedRequestHeaderName(const nsCString& aName);
static bool IsPrivilegedNoCorsRequestHeaderName(const nsCString& aName);
static bool IsSimpleHeader(const nsACString& aName, static bool IsSimpleHeader(const nsACString& aName,
const nsACString& aValue); const nsACString& aValue);

View file

@ -1480,6 +1480,16 @@ nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
nsresult nsPluginInstanceOwner::ProcessKeyPress(nsIDOMEvent* aKeyEvent) nsresult nsPluginInstanceOwner::ProcessKeyPress(nsIDOMEvent* aKeyEvent)
{ {
// ProcessKeyPress() may be called twice with same eKeyPress event because we
// listen in both the default and system event groups (to capture keypresses
// potentially captured by plugins that are not printable keys).
// When this is called in the latter case and the event must be fired in the
// default event group too, we don't need to do anything else and can return.
if (!aKeyEvent->WidgetEventPtr()->mFlags.mOnlySystemGroupDispatchInContent &&
aKeyEvent->WidgetEventPtr()->mFlags.mInSystemGroup) {
return NS_OK;
}
#ifdef XP_MACOSX #ifdef XP_MACOSX
return DispatchKeyToPlugin(aKeyEvent); return DispatchKeyToPlugin(aKeyEvent);
#else #else
@ -2547,6 +2557,7 @@ nsPluginInstanceOwner::Destroy()
content->RemoveEventListener(NS_LITERAL_STRING("mouseover"), this, false); content->RemoveEventListener(NS_LITERAL_STRING("mouseover"), this, false);
content->RemoveEventListener(NS_LITERAL_STRING("mouseout"), this, false); content->RemoveEventListener(NS_LITERAL_STRING("mouseout"), this, false);
content->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, true); content->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, true);
content->RemoveSystemEventListener(NS_LITERAL_STRING("keypress"), this, true);
content->RemoveEventListener(NS_LITERAL_STRING("keydown"), this, true); content->RemoveEventListener(NS_LITERAL_STRING("keydown"), this, true);
content->RemoveEventListener(NS_LITERAL_STRING("keyup"), this, true); content->RemoveEventListener(NS_LITERAL_STRING("keyup"), this, true);
content->RemoveEventListener(NS_LITERAL_STRING("drop"), this, true); content->RemoveEventListener(NS_LITERAL_STRING("drop"), this, true);
@ -2856,25 +2867,22 @@ nsresult nsPluginInstanceOwner::Init(nsIContent* aContent)
// register context menu listener // register context menu listener
mCXMenuListener = new nsPluginDOMContextMenuListener(aContent); mCXMenuListener = new nsPluginDOMContextMenuListener(aContent);
aContent->AddEventListener(NS_LITERAL_STRING("focus"), this, false, aContent->AddEventListener(NS_LITERAL_STRING("focus"), this, false, false);
false); aContent->AddEventListener(NS_LITERAL_STRING("blur"), this, false, false);
aContent->AddEventListener(NS_LITERAL_STRING("blur"), this, false, aContent->AddEventListener(NS_LITERAL_STRING("mouseup"), this, false, false);
false); aContent->AddEventListener(NS_LITERAL_STRING("mousedown"), this, false, false);
aContent->AddEventListener(NS_LITERAL_STRING("mouseup"), this, false, aContent->AddEventListener(NS_LITERAL_STRING("mousemove"), this, false, false);
false); aContent->AddEventListener(NS_LITERAL_STRING("click"), this, false, false);
aContent->AddEventListener(NS_LITERAL_STRING("mousedown"), this, false, aContent->AddEventListener(NS_LITERAL_STRING("dblclick"), this, false, false);
false); aContent->AddEventListener(NS_LITERAL_STRING("mouseover"), this, false, false);
aContent->AddEventListener(NS_LITERAL_STRING("mousemove"), this, false, aContent->AddEventListener(NS_LITERAL_STRING("mouseout"), this, false, false);
false);
aContent->AddEventListener(NS_LITERAL_STRING("click"), this, false, // The "keypress" event should be handled when it's in the default event group
false); // if the event is fired in content.
aContent->AddEventListener(NS_LITERAL_STRING("dblclick"), this, false, // Otherwise, it should be handled when it's in the system event group.
false);
aContent->AddEventListener(NS_LITERAL_STRING("mouseover"), this, false,
false);
aContent->AddEventListener(NS_LITERAL_STRING("mouseout"), this, false,
false);
aContent->AddEventListener(NS_LITERAL_STRING("keypress"), this, true); aContent->AddEventListener(NS_LITERAL_STRING("keypress"), this, true);
aContent->AddSystemEventListener(NS_LITERAL_STRING("keypress"), this, true);
aContent->AddEventListener(NS_LITERAL_STRING("keydown"), this, true); aContent->AddEventListener(NS_LITERAL_STRING("keydown"), this, true);
aContent->AddEventListener(NS_LITERAL_STRING("keyup"), this, true); aContent->AddEventListener(NS_LITERAL_STRING("keyup"), this, true);
aContent->AddEventListener(NS_LITERAL_STRING("drop"), this, true); aContent->AddEventListener(NS_LITERAL_STRING("drop"), this, true);

View file

@ -3071,9 +3071,8 @@ XMLHttpRequestMainThread::SetRequestHeader(const nsACString& aName,
} }
// Step 3 // Step 3
nsAutoCString value(aValue); nsAutoCString value;
static const char kHTTPWhitespace[] = "\n\t\r "; NS_TrimHTTPWhitespace(aValue, value);
value.Trim(kHTTPWhitespace);
// Step 4 // Step 4
if (!NS_IsValidHTTPToken(aName) || !NS_IsReasonableHTTPHeaderValue(value)) { if (!NS_IsValidHTTPToken(aName) || !NS_IsReasonableHTTPHeaderValue(value)) {
@ -3082,7 +3081,7 @@ XMLHttpRequestMainThread::SetRequestHeader(const nsACString& aName,
// Step 5 // Step 5
bool isPrivilegedCaller = IsSystemXHR(); bool isPrivilegedCaller = IsSystemXHR();
bool isForbiddenHeader = nsContentUtils::IsForbiddenRequestHeader(aName); bool isForbiddenHeader = nsContentUtils::IsForbiddenRequestHeader(aName, aValue);
if (!isPrivilegedCaller && isForbiddenHeader) { if (!isPrivilegedCaller && isForbiddenHeader) {
NS_ConvertUTF8toUTF16 name(aName); NS_ConvertUTF8toUTF16 name(aName);
const char16_t* params[] = { name.get() }; const char16_t* params[] = { name.get() };

View file

@ -5235,6 +5235,9 @@ pref("dom.storageManager.enabled", false);
// See application preferences for appropriate defaults. // See application preferences for appropriate defaults.
pref("prompts.authentication_dialog_abuse_limit", 0); pref("prompts.authentication_dialog_abuse_limit", 0);
// Whether content handling dialog is window modal
pref("prompts.content_handling_dialog_modal.enabled", false);
// Whether module scripts (<script type="module">) are enabled for content. // Whether module scripts (<script type="module">) are enabled for content.
pref("dom.moduleScripts.enabled", true); pref("dom.moduleScripts.enabled", true);

View file

@ -520,6 +520,12 @@ bool NS_IsValidHTTPToken(const nsACString &aToken)
return mozilla::net::nsHttp::IsValidToken(aToken); return mozilla::net::nsHttp::IsValidToken(aToken);
} }
void
NS_TrimHTTPWhitespace(const nsACString& aSource, nsACString& aDest)
{
mozilla::net::nsHttp::TrimHTTPWhitespace(aSource, aDest);
}
nsresult nsresult
NS_NewLoadGroup(nsILoadGroup **aResult, nsIPrincipal *aPrincipal) NS_NewLoadGroup(nsILoadGroup **aResult, nsIPrincipal *aPrincipal)
{ {

View file

@ -959,6 +959,11 @@ bool NS_IsReasonableHTTPHeaderValue(const nsACString &aValue);
*/ */
bool NS_IsValidHTTPToken(const nsACString &aToken); bool NS_IsValidHTTPToken(const nsACString &aToken);
/**
* Strip the leading or trailing HTTP whitespace per fetch spec section 2.2.
*/
void NS_TrimHTTPWhitespace(const nsACString& aSource, nsACString& aDest);
/** /**
* Return true if the given request must be upgraded to HTTPS. * Return true if the given request must be upgraded to HTTPS.
*/ */

View file

@ -245,6 +245,18 @@ nsHttp::GetProtocolVersion(uint32_t pv)
} }
} }
// static
void
nsHttp::TrimHTTPWhitespace(const nsACString& aSource, nsACString& aDest)
{
nsAutoCString str(aSource);
// HTTP whitespace 0x09: '\t', 0x0A: '\n', 0x0D: '\r', 0x20: ' '
static const char kHTTPWhitespace[] = "\t\n\r ";
str.Trim(kHTTPWhitespace);
aDest.Assign(str);
}
// static // static
bool bool
nsHttp::IsReasonableHeaderValue(const nsACString &s) nsHttp::IsReasonableHeaderValue(const nsACString &s)

View file

@ -148,6 +148,10 @@ struct nsHttp
static inline bool IsValidToken(const nsACString &s) { static inline bool IsValidToken(const nsACString &s) {
return IsValidToken(s.BeginReading(), s.EndReading()); return IsValidToken(s.BeginReading(), s.EndReading());
} }
// Strip the leading or trailing HTTP whitespace per fetch spec section 2.2.
static void TrimHTTPWhitespace(const nsACString& aSource,
nsACString& aDest);
// Returns true if the specified value is reasonable given the defintion // Returns true if the specified value is reasonable given the defintion
// in RFC 2616 section 4.2. Full strict validation is not performed // in RFC 2616 section 4.2. Full strict validation is not performed

View file

@ -2313,6 +2313,16 @@ WebSocketChannel::CleanupConnection()
{ {
LOG(("WebSocketChannel::CleanupConnection() %p", this)); LOG(("WebSocketChannel::CleanupConnection() %p", this));
// This should run on the Socket Thread to prevent potential races.
bool onSocketThread;
nsresult rv = mSocketThread->IsOnCurrentThread(&onSocketThread);
if (NS_SUCCEEDED(rv) && !onSocketThread) {
mSocketThread->Dispatch(
NewRunnableMethod(this, &WebSocketChannel::CleanupConnection),
NS_DISPATCH_NORMAL);
return;
}
if (mLingeringCloseTimer) { if (mLingeringCloseTimer) {
mLingeringCloseTimer->Cancel(); mLingeringCloseTimer->Cancel();
mLingeringCloseTimer = nullptr; mLingeringCloseTimer = nullptr;

View file

@ -181,11 +181,13 @@ static bool scanArp(char *ip, char *mac, size_t maclen)
if (st == 0 || errno != ENOMEM) { if (st == 0 || errno != ENOMEM) {
break; break;
} }
needed += needed / 8; size_t increased = needed;
increased += increased / 8;
auto tmp = MakeUnique<char[]>(needed); auto tmp = MakeUnique<char[]>(increased);
memcpy(&tmp[0], &buf[0], needed); memcpy(&tmp[0], &buf[0], needed);
buf = Move(tmp); buf = Move(tmp);
needed = increased;
} }
if (st == -1) { if (st == -1) {
return false; return false;

View file

@ -6,9 +6,8 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
// Constants // Constants
const Cc = Components.classes; const {utils: Cu, interfaces: Ci, classes: Cc, results: Cr} = Components;
const Ci = Components.interfaces; Cu.import("resource://gre/modules/Services.jsm");
const Cr = Components.results;
const CONTENT_HANDLING_URL = "chrome://mozapps/content/handling/dialog.xul"; const CONTENT_HANDLING_URL = "chrome://mozapps/content/handling/dialog.xul";
const STRINGBUNDLE_URL = "chrome://mozapps/locale/handling/handling.properties"; const STRINGBUNDLE_URL = "chrome://mozapps/locale/handling/handling.properties";
@ -64,13 +63,16 @@ nsContentDispatchChooser.prototype =
params.appendElement(aURI, false); params.appendElement(aURI, false);
params.appendElement(aWindowContext, false); params.appendElement(aWindowContext, false);
var features = "chrome,dialog=yes,resizable,centerscreen";
if (Services.prefs.getBoolPref("prompts.content_handling_dialog_modal.enabled")) {
features += ",modal";
} else {
features += ",dependent";
}
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher); getService(Ci.nsIWindowWatcher);
ww.openWindow(window, ww.openWindow(window, CONTENT_HANDLING_URL, null, features, params);
CONTENT_HANDLING_URL,
null,
"chrome,dialog=yes,resizable,centerscreen",
params);
}, },
// nsISupports // nsISupports

View file

@ -1715,16 +1715,18 @@ nsLocalFile::GetNativeTarget(nsACString& aResult)
} }
int32_t size = (int32_t)symStat.st_size; int32_t size = (int32_t)symStat.st_size;
char* target = (char*)moz_xmalloc(size + 1); nsAutoCString target;
if (!target) { if (!target.SetLength(size, mozilla::fallible)) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
if (readlink(mPath.get(), target, (size_t)size) < 0) { ssize_t written = readlink(mPath.get(), target.BeginWriting(), size_t(size));
free(target); if (written < 0) {
return NSRESULT_FOR_ERRNO(); return NSRESULT_FOR_ERRNO();
} }
target[size] = '\0'; // Target might have changed since the lstat call, or lstat might lie, see bug
// 1791029.
target.Truncate(written);
nsresult rv = NS_OK; nsresult rv = NS_OK;
nsCOMPtr<nsIFile> self(this); nsCOMPtr<nsIFile> self(this);
@ -1740,7 +1742,7 @@ nsLocalFile::GetNativeTarget(nsACString& aResult)
if (NS_FAILED(rv = self->GetParent(getter_AddRefs(parent)))) { if (NS_FAILED(rv = self->GetParent(getter_AddRefs(parent)))) {
break; break;
} }
if (NS_FAILED(rv = parent->AppendRelativeNativePath(nsDependentCString(target)))) { if (NS_FAILED(rv = parent->AppendRelativeNativePath(target))) {
break; break;
} }
if (NS_FAILED(rv = parent->GetNativePath(aResult))) { if (NS_FAILED(rv = parent->GetNativePath(aResult))) {
@ -1765,26 +1767,24 @@ nsLocalFile::GetNativeTarget(nsACString& aResult)
} }
int32_t newSize = (int32_t)symStat.st_size; int32_t newSize = (int32_t)symStat.st_size;
if (newSize > size) { size = newSize;
char* newTarget = (char*)moz_xrealloc(target, newSize + 1); nsAutoCString newTarget;
if (!newTarget) { if (!newTarget.SetLength(size, mozilla::fallible)) {
rv = NS_ERROR_OUT_OF_MEMORY; rv = NS_ERROR_OUT_OF_MEMORY;
break; break;
}
target = newTarget;
size = newSize;
} }
int32_t linkLen = readlink(flatRetval.get(), target, size); ssize_t linkLen = readlink(flatRetval.get(), newTarget.BeginWriting(), size);
if (linkLen == -1) { if (linkLen == -1) {
rv = NSRESULT_FOR_ERRNO(); rv = NSRESULT_FOR_ERRNO();
break; break;
} }
target[linkLen] = '\0'; // Target might have changed since the lstat call, or lstat might lie, see bug
// 1791029.
newTarget.Truncate(linkLen);
target = newTarget;
} }
free(target);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
aResult.Truncate(); aResult.Truncate();
} }