merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-10-16 16:07:06 +02:00
commit 5cbd2e1c3c
297 changed files with 5795 additions and 7658 deletions

View File

@ -178,8 +178,6 @@ button {
input[type="radio"],
input[type="checkbox"] {
max-width: 14px;
max-height: 14px;
border: 1px solid #a7a7a7 !important;
padding: 2px 1px 2px 1px;
}

View File

@ -1,58 +1,95 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
"use strict";
let tab;
let notification;
let notificationURL = "http://example.org/browser/browser/base/content/test/general/file_dom_notifications.html";
function test () {
waitForExplicitFinish();
let pm = Services.perms;
registerCleanupFunction(function() {
pm.remove(notificationURL, "desktop-notification");
gBrowser.removeTab(tab);
window.restore();
});
pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
tab = gBrowser.addTab(notificationURL);
tab.linkedBrowser.addEventListener("load", onLoad, true);
}
function onLoad() {
isnot(gBrowser.selectedTab, tab, "Notification page loaded as a background tab");
tab.linkedBrowser.removeEventListener("load", onLoad, true);
let win = tab.linkedBrowser.contentWindow.wrappedJSObject;
notification = win.showNotification();
notification.addEventListener("show", onAlertShowing);
}
function onAlertShowing() {
info("Notification alert showing");
notification.removeEventListener("show", onAlertShowing);
let alertWindow = findChromeWindowByURI("chrome://global/content/alerts/alert.xul");
if (!alertWindow) {
todo(false, "Notifications don't use XUL windows on all platforms.");
notification.close();
finish();
return;
}
gBrowser.tabContainer.addEventListener("TabSelect", onTabSelect);
EventUtils.synthesizeMouseAtCenter(alertWindow.document.getElementById("alertTitleLabel"), {}, alertWindow);
info("Clicked on notification");
alertWindow.close();
}
function onTabSelect() {
gBrowser.tabContainer.removeEventListener("TabSelect", onTabSelect);
is(gBrowser.selectedTab.linkedBrowser.contentWindow.location.href, notificationURL,
"Notification tab should be selected.");
finish();
}
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
"use strict";
let tab;
let notification;
let notificationURL = "http://example.org/browser/browser/base/content/test/general/file_dom_notifications.html";
let newWindowOpenedFromTab;
function test () {
waitForExplicitFinish();
let pm = Services.perms;
registerCleanupFunction(function() {
pm.remove(notificationURL, "desktop-notification");
gBrowser.removeTab(tab);
window.restore();
});
pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
tab = gBrowser.addTab(notificationURL);
tab.linkedBrowser.addEventListener("load", onLoad, true);
}
function onLoad() {
isnot(gBrowser.selectedTab, tab, "Notification page loaded as a background tab");
tab.linkedBrowser.removeEventListener("load", onLoad, true);
let win = tab.linkedBrowser.contentWindow.wrappedJSObject;
win.newWindow = win.open("about:blank", "", "height=100,width=100");
newWindowOpenedFromTab = win.newWindow;
win.newWindow.addEventListener("load", function() {
info("new window loaded");
win.newWindow.addEventListener("blur", function b() {
info("new window got blur");
win.newWindow.removeEventListener("blur", b);
notification = win.showNotification1();
win.newWindow.addEventListener("focus", onNewWindowFocused);
notification.addEventListener("show", onAlertShowing);
});
function waitUntilNewWindowHasFocus() {
if (!win.newWindow.document.hasFocus()) {
setTimeout(waitUntilNewWindowHasFocus, 50);
} else {
// Focus another window so that new window gets blur event.
gBrowser.selectedTab.linkedBrowser.contentWindow.focus();
}
}
win.newWindow.focus();
waitUntilNewWindowHasFocus();
});
}
function onAlertShowing() {
info("Notification alert showing");
notification.removeEventListener("show", onAlertShowing);
let alertWindow = findChromeWindowByURI("chrome://global/content/alerts/alert.xul");
if (!alertWindow) {
todo(false, "Notifications don't use XUL windows on all platforms.");
notification.close();
newWindowOpenedFromTab.close();
finish();
return;
}
gBrowser.tabContainer.addEventListener("TabSelect", onTabSelect);
EventUtils.synthesizeMouseAtCenter(alertWindow.document.getElementById("alertTitleLabel"), {}, alertWindow);
info("Clicked on notification");
alertWindow.close();
}
function onNewWindowFocused(event) {
event.target.close();
isnot(gBrowser.selectedTab, tab, "Notification page loaded as a background tab");
// Using timeout to test that something do *not* happen!
setTimeout(openSecondNotification, 50);
}
function openSecondNotification() {
isnot(gBrowser.selectedTab, tab, "Notification page loaded as a background tab");
let win = tab.linkedBrowser.contentWindow.wrappedJSObject;
notification = win.showNotification2();
notification.addEventListener("show", onAlertShowing);
}
function onTabSelect() {
gBrowser.tabContainer.removeEventListener("TabSelect", onTabSelect);
is(gBrowser.selectedTab.linkedBrowser.contentWindow.location.href, notificationURL,
"Notification tab should be selected.");
finish();
}

View File

@ -1,23 +1,40 @@
<html>
<head>
<script>
"use strict";
function showNotification() {
var options = {
dir: undefined,
lang: undefined,
body: "Test body",
tag: "Test tag",
icon: undefined,
};
return new Notification("Test title", options);
}
</script>
</head>
<body>
<form id="notificationForm" onsubmit="showNotification();">
<input type="submit" value="Show notification" id="submit"/>
</form>
</body>
</html>
<html>
<head>
<script>
"use strict";
function showNotification1() {
var options = {
dir: undefined,
lang: undefined,
body: "Test body",
tag: "Test tag",
icon: undefined,
};
var n = new Notification("Test title", options);
n.addEventListener("click", function(event) {
event.preventDefault();
dump("Should focus new window.");
newWindow.focus();
});
return n;
}
function showNotification2() {
var options = {
dir: undefined,
lang: undefined,
body: "Test body",
tag: "Test tag",
icon: undefined,
};
return new Notification("Test title", options);
}
</script>
</head>
<body>
<form id="notificationForm" onsubmit="showNotification();">
<input type="submit" value="Show notification" id="submit"/>
</form>
</body>
</html>

View File

@ -87,6 +87,7 @@ CERT_FilterCertListByUsage
CERT_FilterCertListForUserCerts
CERT_FindCertByDERCert
CERT_FindCertByIssuerAndSN
CERT_FindCertByName
CERT_FindCertByNickname
CERT_FindCertByNicknameOrEmailAddr
CERT_FindCertExtension
@ -159,6 +160,8 @@ DER_GetInteger_Util
DER_Lengths
DER_SetUInteger
DER_UTCTimeToTime_Util
DSAU_DecodeDerSigToLen
DSAU_EncodeDerSigWithLen
DTLS_GetHandshakeTimeout
DTLS_ImportFD
HASH_Begin
@ -307,6 +310,7 @@ PK11_DeriveWithTemplate
PK11_DestroyContext
PK11_DestroyGenericObject
PK11_DestroyMergeLog
PK11_DestroyObject
PK11_DestroyTokenObject
PK11_DigestBegin
PK11_DigestFinal
@ -368,6 +372,7 @@ PK11_ImportCert
PK11_ImportCertForKey
PK11_ImportCRL
PK11_ImportDERPrivateKeyInfoAndReturnKey
PK11_ImportPublicKey
PK11_ImportSymKey
PK11_InitPin
PK11_IsDisabled
@ -632,6 +637,7 @@ SSL_CipherPrefSet
SSL_CipherPrefSetDefault
SSL_ClearSessionCache
SSL_ConfigSecureServer
SSL_ConfigSecureServerWithCertChain
SSL_ConfigServerSessionIDCache
SSL_ExportKeyingMaterial
SSL_ForceHandshake
@ -670,6 +676,7 @@ VFY_CreateContext
VFY_DestroyContext
VFY_End
VFY_Update
VFY_VerifyData
VFY_VerifyDataDirect
VFY_VerifyDataWithAlgorithmID
_SGN_VerifyPKCS1DigestInfo

View File

@ -7241,9 +7241,6 @@ dnl our own linker.
if test "$OS_TARGET" = Android; then
WRAP_LDFLAGS="${WRAP_LDFLAGS} -L$_objdir/dist/lib -lmozglue"
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=PR_GetEnv,--wrap=PR_SetEnv"
if test -z "$gonkdir"; then
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=memccpy,--wrap=memchr,--wrap=memrchr,--wrap=memcmp,--wrap=memcpy,--wrap=memmove,--wrap=memset,--wrap=memmem,--wrap=index,--wrap=strchr,--wrap=strrchr,--wrap=strlen,--wrap=strcmp,--wrap=strcpy,--wrap=strcat,--wrap=strcasecmp,--wrap=strncasecmp,--wrap=strstr,--wrap=strcasestr,--wrap=strtok,--wrap=strtok_r,--wrap=strerror,--wrap=strerror_r,--wrap=strnlen,--wrap=strncat,--wrap=strncmp,--wrap=strncpy,--wrap=strlcat,--wrap=strlcpy,--wrap=strcspn,--wrap=strpbrk,--wrap=strsep,--wrap=strspn,--wrap=strcoll,--wrap=strxfrm"
fi
if test "$MOZ_WIDGET_TOOLKIT" = gonk -a -n "$MOZ_NUWA_PROCESS"; then
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=pthread_create,--wrap=epoll_wait,--wrap=poll,--wrap=pthread_cond_timedwait,--wrap=__pthread_cond_timedwait,--wrap=pthread_cond_wait,--wrap=epoll_create,--wrap=epoll_ctl,--wrap=close,--wrap=pthread_key_create,--wrap=pthread_key_delete,--wrap=socketpair,--wrap=pthread_self,--wrap=pthread_mutex_lock,--wrap=pthread_join,--wrap=pipe,--wrap=pipe2,--wrap=tgkill"
fi

View File

@ -435,7 +435,7 @@ DOMMatrix::TranslateSelf(double aTx,
if (mMatrix3D || aTz != 0) {
Ensure3DMatrix();
mMatrix3D->Translate(aTx, aTy, aTz);
mMatrix3D->PreTranslate(aTx, aTy, aTz);
} else {
mMatrix2D->PreTranslate(aTx, aTy);
}

View File

@ -27,7 +27,6 @@
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIScriptError.h"
#include "mozilla/dom/EncodingUtils.h"
#include "nsIChannelPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsContentUtils.h"
#include "mozilla/Preferences.h"
@ -737,17 +736,7 @@ EventSource::InitChannelAndRequestEventSource()
nsLoadFlags loadFlags;
loadFlags = nsIRequest::LOAD_BACKGROUND | nsIRequest::LOAD_BYPASS_CACHE;
// get Content Security Policy from principal to pass into channel
nsCOMPtr<nsIChannelPolicy> channelPolicy;
nsCOMPtr<nsIContentSecurityPolicy> csp;
nsresult rv = mPrincipal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
channelPolicy->SetContentSecurityPolicy(csp);
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_DATAREQUEST);
}
nsresult rv;
nsIScriptContext* sc = GetContextForEventHandlers(&rv);
nsCOMPtr<nsIDocument> doc =
nsContentUtils::GetDocumentFromScriptContext(sc);
@ -760,7 +749,6 @@ EventSource::InitChannelAndRequestEventSource()
doc,
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
nsIContentPolicy::TYPE_DATAREQUEST,
channelPolicy, // aChannelPolicy
mLoadGroup, // loadGroup
nullptr, // aCallbacks
loadFlags); // aLoadFlags
@ -771,7 +759,6 @@ EventSource::InitChannelAndRequestEventSource()
mPrincipal,
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
nsIContentPolicy::TYPE_DATAREQUEST,
channelPolicy, // aChannelPolicy
mLoadGroup, // loadGroup
nullptr, // aCallbacks
loadFlags); // aLoadFlags

View File

@ -12,7 +12,6 @@
#include "nsContentUtils.h"
#include "nsCrossSiteListenerProxy.h"
#include "nsIChannel.h"
#include "nsIChannelPolicy.h"
#include "nsIContentPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIDocument.h"
@ -485,23 +484,12 @@ ImportLoader::Open()
NS_ENSURE_SUCCESS_VOID(rv);
nsCOMPtr<nsILoadGroup> loadGroup = master->GetDocumentLoadGroup();
nsCOMPtr<nsIChannelPolicy> channelPolicy;
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = principal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS_VOID(rv);
if (csp) {
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
channelPolicy->SetContentSecurityPolicy(csp);
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_SUBDOCUMENT);
}
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel),
mURI,
mImportParent,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_SUBDOCUMENT,
channelPolicy,
loadGroup,
nullptr, // aCallbacks
nsIRequest::LOAD_BACKGROUND);

View File

@ -112,7 +112,6 @@ UNIFIED_SOURCES += [
'nsAttrValue.cpp',
'nsAttrValueOrString.cpp',
'nsCCUncollectableMarker.cpp',
'nsChannelPolicy.cpp',
'nsContentAreaDragDrop.cpp',
'nsContentIterator.cpp',
'nsContentList.cpp',

View File

@ -11,7 +11,6 @@
#include "nsCSPService.h"
#include "nsError.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIChannelPolicy.h"
#include "nsIClassInfoImpl.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
@ -25,12 +24,10 @@
#include "nsIObjectOutputStream.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIPropertyBag2.h"
#include "nsIStringStream.h"
#include "nsIUploadChannel.h"
#include "nsIScriptError.h"
#include "nsIWebNavigation.h"
#include "nsIWritablePropertyBag2.h"
#include "nsNetUtil.h"
#include "nsNullPrincipal.h"
#include "nsIContentPolicy.h"

View File

@ -12,17 +12,13 @@
#include "nsIContent.h"
#include "nsCSPService.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIChannelPolicy.h"
#include "nsIChannelEventSink.h"
#include "nsIPropertyBag2.h"
#include "nsIWritablePropertyBag2.h"
#include "nsError.h"
#include "nsChannelProperties.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsAsyncRedirectVerifyHelper.h"
#include "mozilla/Preferences.h"
#include "nsIScriptError.h"
#include "nsContentUtils.h"
#include "nsContentPolicyUtils.h"
#include "nsPrincipal.h"
using namespace mozilla;
@ -236,53 +232,56 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
{
nsAsyncRedirectAutoCallback autoCallback(callback);
// get the Content Security Policy and load type from the property bag
nsCOMPtr<nsISupports> policyContainer;
nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(oldChannel));
if (!props)
nsCOMPtr<nsILoadInfo> loadInfo;
nsresult rv = oldChannel->GetLoadInfo(getter_AddRefs(loadInfo));
// if no loadInfo on the channel, nothing for us to do
if (!loadInfo) {
return NS_OK;
}
props->GetPropertyAsInterface(NS_CHANNEL_PROP_CHANNEL_POLICY,
NS_GET_IID(nsISupports),
getter_AddRefs(policyContainer));
// The loadInfo must not necessarily contain a Node, hence we try to query
// the CSP in the following order:
// a) Get the Node, the Principal of that Node, and the CSP of that Principal
// b) Get the Principal and the CSP of that Principal
// see if we have a valid nsIChannelPolicy containing CSP and load type
nsCOMPtr<nsIChannelPolicy> channelPolicy(do_QueryInterface(policyContainer));
if (!channelPolicy)
return NS_OK;
nsCOMPtr<nsISupports> supports;
nsCOMPtr<nsINode> loadingNode = loadInfo->LoadingNode();
nsCOMPtr<nsIPrincipal> principal = loadingNode ?
loadingNode->NodePrincipal() :
loadInfo->LoadingPrincipal();
NS_ASSERTION(principal, "Can not evaluate CSP without a principal");
nsCOMPtr<nsIContentSecurityPolicy> csp;
channelPolicy->GetContentSecurityPolicy(getter_AddRefs(supports));
csp = do_QueryInterface(supports);
uint32_t loadType;
channelPolicy->GetLoadType(&loadType);
rv = principal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
// if no CSP in the channelPolicy, nothing for us to add to the channel
if (!csp)
// if there is no CSP, nothing for us to do
if (!csp) {
return NS_OK;
}
/* Since redirecting channels don't call into nsIContentPolicy, we call our
* Content Policy implementation directly when redirects occur. When channels
* are created using NS_NewChannel(), callers can optionally pass in a
* nsIChannelPolicy containing a CSP object and load type, which is placed in
* the new channel's property bag. This container is propagated forward when
* channels redirect.
* Content Policy implementation directly when redirects occur using the
* information set in the LoadInfo when channels are created.
*
* We check if the CSP permits this host for this type of load, if not,
* we cancel the load now.
*/
// Does the CSP permit this host for this type of load?
// If not, cancel the load now.
nsCOMPtr<nsIURI> newUri;
newChannel->GetURI(getter_AddRefs(newUri));
rv = newChannel->GetURI(getter_AddRefs(newUri));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> originalUri;
oldChannel->GetOriginalURI(getter_AddRefs(originalUri));
rv = oldChannel->GetOriginalURI(getter_AddRefs(originalUri));
NS_ENSURE_SUCCESS(rv, rv);
nsContentPolicyType policyType = loadInfo->GetContentPolicyType();
int16_t aDecision = nsIContentPolicy::ACCEPT;
csp->ShouldLoad(loadType, // load type per nsIContentPolicy (uint32_t)
newUri, // nsIURI
nullptr, // nsIURI
nullptr, // nsISupports
EmptyCString(), // ACString - MIME guess
originalUri, // nsISupports - extra
csp->ShouldLoad(policyType, // load type per nsIContentPolicy (uint32_t)
newUri, // nsIURI
nullptr, // nsIURI
nullptr, // nsISupports
EmptyCString(), // ACString - MIME guess
originalUri, // aMimeTypeGuess
&aDecision);
#ifdef PR_LOGGING
@ -302,36 +301,9 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
#endif
// if ShouldLoad doesn't accept the load, cancel the request
if (aDecision != 1) {
if (!NS_CP_ACCEPTED(aDecision)) {
autoCallback.DontCallback();
return NS_BINDING_FAILED;
}
// the redirect is permitted, so propagate the Content Security Policy
// and load type to the redirecting channel
nsresult rv;
nsCOMPtr<nsIWritablePropertyBag2> props2 = do_QueryInterface(newChannel);
if (props2) {
rv = props2->SetPropertyAsInterface(NS_CHANNEL_PROP_CHANNEL_POLICY,
channelPolicy);
if (NS_SUCCEEDED(rv)) {
return NS_OK;
}
}
// The redirecting channel isn't a writable property bag, we won't be able
// to enforce the load policy if it redirects again, so we stop it now.
nsAutoCString newUriSpec;
rv = newUri->GetSpec(newUriSpec);
NS_ConvertUTF8toUTF16 unicodeSpec(newUriSpec);
const char16_t *formatParams[] = { unicodeSpec.get() };
if (NS_SUCCEEDED(rv)) {
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Redirect Error"), nullptr,
nsContentUtils::eDOM_PROPERTIES,
"InvalidRedirectChannelWarning",
formatParams, 1);
}
return NS_BINDING_FAILED;
return NS_OK;
}

View File

@ -1,46 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsChannelPolicy.h"
nsChannelPolicy::nsChannelPolicy()
: mLoadType(0)
{
}
nsChannelPolicy::~nsChannelPolicy()
{
}
NS_IMPL_ISUPPORTS(nsChannelPolicy, nsIChannelPolicy)
NS_IMETHODIMP
nsChannelPolicy::GetLoadType(uint32_t *aLoadType)
{
*aLoadType = mLoadType;
return NS_OK;
}
NS_IMETHODIMP
nsChannelPolicy::SetLoadType(uint32_t aLoadType)
{
mLoadType = aLoadType;
return NS_OK;
}
NS_IMETHODIMP
nsChannelPolicy::GetContentSecurityPolicy(nsISupports **aCSP)
{
*aCSP = mCSP;
NS_IF_ADDREF(*aCSP);
return NS_OK;
}
NS_IMETHODIMP
nsChannelPolicy::SetContentSecurityPolicy(nsISupports *aCSP)
{
mCSP = aCSP;
return NS_OK;
}

View File

@ -1,37 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 nsChannelPolicy_h___
#define nsChannelPolicy_h___
#include "nsCOMPtr.h"
#include "nsIChannelPolicy.h"
#define NSCHANNELPOLICY_CONTRACTID "@mozilla.org/nschannelpolicy;1"
#define NSCHANNELPOLICY_CID \
{ 0xd396b3cd, 0xf164, 0x4ce8, \
{ 0x93, 0xa7, 0xe3, 0x85, 0xe1, 0x46, 0x56, 0x3c } }
class nsChannelPolicy : public nsIChannelPolicy
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICHANNELPOLICY
nsChannelPolicy();
protected:
virtual ~nsChannelPolicy();
/* Represents the type of content being loaded in the channel per
* nsIContentPolicy, e.g. TYPE_IMAGE, TYPE_SCRIPT
*/
unsigned long mLoadType;
/* pointer to a Content Security Policy object if available */
nsCOMPtr<nsISupports> mCSP;
};
#endif /* nsChannelPolicy_h___ */

View File

@ -59,7 +59,6 @@
#include "nsAttrValueInlines.h"
#include "nsBindingManager.h"
#include "nsCCUncollectableMarker.h"
#include "nsChannelPolicy.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsCOMPtr.h"
#include "nsContentCreatorFunctions.h"
@ -88,7 +87,6 @@
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsICategoryManager.h"
#include "nsIChannelEventSink.h"
#include "nsIChannelPolicy.h"
#include "nsICharsetDetectionObserver.h"
#include "nsIChromeRegistry.h"
#include "nsIConsoleService.h"
@ -3007,20 +3005,6 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
NS_ASSERTION(loadGroup || IsFontTableURI(documentURI),
"Could not get loadgroup; onload may fire too early");
// check for a Content Security Policy to pass down to the channel that
// will get created to load the image
nsCOMPtr<nsIChannelPolicy> channelPolicy;
nsCOMPtr<nsIContentSecurityPolicy> csp;
if (aLoadingPrincipal) {
nsresult rv = aLoadingPrincipal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
channelPolicy->SetContentSecurityPolicy(csp);
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE);
}
}
// Make the URI immutable so people won't change it under us
NS_TryToSetImmutable(aURI);
@ -3035,7 +3019,6 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
aLoadingDocument, /* uniquification key */
aLoadFlags, /* load flags */
nullptr, /* cache key */
channelPolicy, /* CSP info */
initiatorType, /* the load initiator */
aRequest);
}

View File

@ -1122,7 +1122,6 @@ NS_StartCORSPreflight(nsIChannel* aRequestChannel,
rv = NS_NewChannelInternal(getter_AddRefs(preflightChannel),
uri,
loadInfo,
nullptr, // aChannelPolicy
loadGroup,
nullptr, // aCallbacks
loadFlags);
@ -1134,7 +1133,6 @@ NS_StartCORSPreflight(nsIChannel* aRequestChannel,
nsContentUtils::GetSystemPrincipal(),
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_OTHER,
nullptr, // aChannelPolicy
loadGroup,
nullptr, // aCallbacks
loadFlags);

View File

@ -1330,7 +1330,6 @@ nsExternalResourceMap::PendingLoad::StartLoad(nsIURI* aURI,
aRequestingNode,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_OTHER,
nullptr, // aChannelPolicy
loadGroup,
req); // aCallbacks

View File

@ -65,8 +65,6 @@
#include "nsObjectLoadingContent.h"
#include "mozAutoDocUpdate.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIChannelPolicy.h"
#include "nsChannelPolicy.h"
#include "GeckoProfiler.h"
#include "nsPluginFrame.h"
#include "nsDOMClassInfo.h"
@ -2492,15 +2490,6 @@ nsObjectLoadingContent::OpenChannel()
nsCOMPtr<nsILoadGroup> group = doc->GetDocumentLoadGroup();
nsCOMPtr<nsIChannel> chan;
nsCOMPtr<nsIChannelPolicy> channelPolicy;
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
channelPolicy->SetContentSecurityPolicy(csp);
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_OBJECT);
}
nsRefPtr<ObjectInterfaceRequestorShim> shim =
new ObjectInterfaceRequestorShim(this);
@ -2522,7 +2511,6 @@ nsObjectLoadingContent::OpenChannel()
thisContent,
securityFlags,
nsIContentPolicy::TYPE_OBJECT,
channelPolicy,
group, // aLoadGroup
shim, // aCallbacks
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |

View File

@ -41,8 +41,6 @@
#include "nsDocShellCID.h"
#include "nsIContentSecurityPolicy.h"
#include "prlog.h"
#include "nsIChannelPolicy.h"
#include "nsChannelPolicy.h"
#include "nsCRT.h"
#include "nsContentCreatorFunctions.h"
#include "nsCrossSiteListenerProxy.h"
@ -307,25 +305,12 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
return NS_OK;
}
// check for a Content Security Policy to pass down to the channel
// that will be created to load the script
nsCOMPtr<nsIChannelPolicy> channelPolicy;
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = mDocument->NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
channelPolicy->SetContentSecurityPolicy(csp);
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_SCRIPT);
}
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel),
aRequest->mURI,
mDocument,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_SCRIPT,
channelPolicy,
loadGroup,
prompter,
nsIRequest::LOAD_NORMAL |

View File

@ -315,7 +315,6 @@ nsSyncLoadService::LoadDocument(nsIURI *aURI, nsIPrincipal *aLoaderPrincipal,
aLoaderPrincipal,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_OTHER,
nullptr, // aChannelPolicy
aLoadGroup);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -52,8 +52,6 @@
#include "nsIPromptFactory.h"
#include "nsIWindowWatcher.h"
#include "nsIConsoleService.h"
#include "nsIChannelPolicy.h"
#include "nsChannelPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsAsyncRedirectVerifyHelper.h"
#include "nsStringBuffer.h"
@ -474,6 +472,10 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLHttpRequest,
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mXMLParserStreamListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResponseBlob)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMFile)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotificationCallbacks)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChannelEventSink)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mProgressEventSink)
@ -492,6 +494,10 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXMLHttpRequest,
NS_IMPL_CYCLE_COLLECTION_UNLINK(mXMLParserStreamListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mResponseBlob)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMFile)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNotificationCallbacks)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChannelEventSink)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mProgressEventSink)
@ -1724,17 +1730,6 @@ nsXMLHttpRequest::Open(const nsACString& inMethod, const nsACString& url,
// will be automatically aborted if the user leaves the page.
nsCOMPtr<nsILoadGroup> loadGroup = GetLoadGroup();
// get Content Security Policy from principal to pass into channel
nsCOMPtr<nsIChannelPolicy> channelPolicy;
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = mPrincipal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
channelPolicy->SetContentSecurityPolicy(csp);
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_XMLHTTPREQUEST);
}
nsSecurityFlags secFlags = nsILoadInfo::SEC_NORMAL;
if (IsSystemXHR()) {
// Don't give this document the system principal. We need to keep track of
@ -1754,7 +1749,6 @@ nsXMLHttpRequest::Open(const nsACString& inMethod, const nsACString& url,
doc,
secFlags,
nsIContentPolicy::TYPE_XMLHTTPREQUEST,
channelPolicy,
loadGroup,
nullptr, // aCallbacks
nsIRequest::LOAD_BACKGROUND);
@ -1765,7 +1759,6 @@ nsXMLHttpRequest::Open(const nsACString& inMethod, const nsACString& url,
mPrincipal,
secFlags,
nsIContentPolicy::TYPE_XMLHTTPREQUEST,
channelPolicy,
loadGroup,
nullptr, // aCallbacks
nsIRequest::LOAD_BACKGROUND);

View File

@ -291,6 +291,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(https not working, bug
[test_bug340571.html]
[test_bug343596.html]
[test_bug345339.html]
skip-if = e10s # Bug 1081453 - shutdown leaks with e10s and WebIDL dom::File
[test_bug346485.html]
[test_bug352728.html]
[test_bug352728.xhtml]

View File

@ -99,8 +99,6 @@ static PRLogModuleInfo* gMediaElementEventsLog;
#endif
#include "nsIContentSecurityPolicy.h"
#include "nsIChannelPolicy.h"
#include "nsChannelPolicy.h"
#include "mozilla/Preferences.h"
@ -1170,25 +1168,12 @@ nsresult HTMLMediaElement::LoadResource()
}
nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
// check for a Content Security Policy to pass down to the channel
// created to load the media content
nsCOMPtr<nsIChannelPolicy> channelPolicy;
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv,rv);
if (csp) {
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
channelPolicy->SetContentSecurityPolicy(csp);
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_MEDIA);
}
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel),
mLoadingSrc,
static_cast<Element*>(this),
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_MEDIA,
channelPolicy,
loadGroup,
nullptr, // aCallbacks
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |

View File

@ -21,7 +21,6 @@
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsICachingChannel.h"
#include "nsIChannelEventSink.h"
#include "nsIChannelPolicy.h"
#include "nsIContentPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIDocument.h"
@ -237,20 +236,6 @@ HTMLTrackElement::LoadResource()
CreateTextTrack();
}
// Check for a Content Security Policy to pass down to the channel
// created to load the media content.
nsCOMPtr<nsIChannelPolicy> channelPolicy;
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv));
if (csp) {
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
if (!channelPolicy) {
return;
}
channelPolicy->SetContentSecurityPolicy(csp);
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_MEDIA);
}
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsILoadGroup> loadGroup = OwnerDoc()->GetDocumentLoadGroup();
rv = NS_NewChannel(getter_AddRefs(channel),
@ -258,7 +243,6 @@ HTMLTrackElement::LoadResource()
static_cast<Element*>(this),
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_MEDIA,
channelPolicy,
loadGroup);
NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv));

View File

@ -291,16 +291,11 @@ static const nsAttrValue::EnumTable kDirTable[] = {
void
nsGenericHTMLElement::GetAccessKeyLabel(nsString& aLabel)
{
//XXXsmaug We shouldn't need PresContext for this.
nsPresContext *presContext = GetPresContext(eForComposedDoc);
if (presContext) {
nsAutoString suffix;
GetAccessKey(suffix);
if (!suffix.IsEmpty() &&
presContext->EventStateManager()->GetAccessKeyLabelPrefix(aLabel)) {
aLabel.Append(suffix);
}
nsAutoString suffix;
GetAccessKey(suffix);
if (!suffix.IsEmpty()) {
EventStateManager::GetAccessKeyLabelPrefix(this, aLabel);
aLabel.Append(suffix);
}
}

View File

@ -1516,7 +1516,6 @@ nsHTMLDocument::Open(JSContext* cx,
callerDoc,
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
nsIContentPolicy::TYPE_OTHER,
nullptr, // aChannelPolicy
group);
if (rv.Failed()) {

View File

@ -464,7 +464,7 @@ AsyncCubebTask::AsyncCubebTask(AudioCallbackDriver* aDriver, AsyncCubebOperation
mOperation(aOperation),
mShutdownGrip(aDriver->GraphImpl())
{
MOZ_ASSERT(mDriver->mAudioStream || aOperation == INIT, "No audio stream !");
NS_WARN_IF_FALSE(mDriver->mAudioStream || aOperation == INIT, "No audio stream !");
}
AsyncCubebTask::~AsyncCubebTask()

View File

@ -924,7 +924,6 @@ ChannelMediaResource::RecreateChannel()
element,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_MEDIA,
nullptr, // aChannelPolicy
loadGroup,
nullptr, // aCallbacks
loadFlags);
@ -1442,7 +1441,6 @@ already_AddRefed<MediaResource> FileMediaResource::CloneData(MediaDecoder* aDeco
element,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_MEDIA,
nullptr, // aChannelPolicy
loadGroup);
if (NS_FAILED(rv))

View File

@ -202,24 +202,26 @@ void
MediaSourceReader::Shutdown()
{
MediaDecoderReader::Shutdown();
for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
mTrackBuffers[i]->Shutdown();
}
mAudioTrack = nullptr;
mAudioReader = nullptr;
mVideoTrack = nullptr;
mVideoReader = nullptr;
for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
mTrackBuffers[i]->Shutdown();
}
mTrackBuffers.Clear();
}
void
MediaSourceReader::BreakCycles()
{
MediaDecoderReader::BreakCycles();
mAudioTrack = nullptr;
mAudioReader = nullptr;
mVideoTrack = nullptr;
mVideoReader = nullptr;
// These were cleared in Shutdown().
MOZ_ASSERT(!mAudioTrack);
MOZ_ASSERT(!mAudioReader);
MOZ_ASSERT(!mVideoTrack);
MOZ_ASSERT(!mVideoReader);
for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
mTrackBuffers[i]->BreakCycles();
}

View File

@ -416,8 +416,21 @@ SourceBuffer::Dump(const char* aPath)
}
#endif
NS_IMPL_CYCLE_COLLECTION_INHERITED(SourceBuffer, DOMEventTargetHelper,
mMediaSource)
NS_IMPL_CYCLE_COLLECTION_CLASS(SourceBuffer)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SourceBuffer)
// Tell the TrackBuffer to end its current SourceBufferResource.
TrackBuffer* track = tmp->mTrackBuffer;
if (track) {
track->Detach();
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaSource)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SourceBuffer,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaSource)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_ADDREF_INHERITED(SourceBuffer, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(SourceBuffer, DOMEventTargetHelper)

View File

@ -54,31 +54,22 @@ TrackBuffer::~TrackBuffer()
class ReleaseDecoderTask : public nsRunnable {
public:
explicit ReleaseDecoderTask(SourceBufferDecoder* aDecoder)
: mDecoder(aDecoder)
{
mDecoders.AppendElement(aDecoder);
}
explicit ReleaseDecoderTask(nsTArray<nsRefPtr<SourceBufferDecoder>>& aDecoders)
{
mDecoders.SwapElements(aDecoders);
}
NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL {
mDecoders.Clear();
mDecoder = nullptr;
return NS_OK;
}
private:
nsTArray<nsRefPtr<SourceBufferDecoder>> mDecoders;
nsRefPtr<SourceBufferDecoder> mDecoder;
};
void
TrackBuffer::Shutdown()
{
// End the SourceBufferResource associated with mCurrentDecoder, which will
// unblock any decoder initialization in ReadMetadata().
DiscardDecoder();
// Finish any decoder initialization, which may add to mInitializedDecoders.
// Shutdown waits for any pending events, which may require the monitor,
// so we must not hold the monitor during this call.
@ -91,8 +82,6 @@ TrackBuffer::Shutdown()
mDecoders[i]->GetReader()->Shutdown();
}
mInitializedDecoders.Clear();
NS_DispatchToMainThread(new ReleaseDecoderTask(mDecoders));
MOZ_ASSERT(mDecoders.IsEmpty());
mParentDecoder = nullptr;
}
@ -399,13 +388,16 @@ TrackBuffer::ContainsTime(int64_t aTime)
void
TrackBuffer::BreakCycles()
{
MOZ_ASSERT(NS_IsMainThread());
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
mDecoders[i]->GetReader()->BreakCycles();
}
mInitializedDecoders.Clear();
NS_DispatchToMainThread(new ReleaseDecoderTask(mDecoders));
MOZ_ASSERT(mDecoders.IsEmpty());
mParentDecoder = nullptr;
mDecoders.Clear();
// These are cleared in Shutdown()
MOZ_ASSERT(mInitializedDecoders.IsEmpty());
MOZ_ASSERT(!mParentDecoder);
}
void

View File

@ -460,7 +460,6 @@ skip-if = true # bug 1021673
[test_standalone.html]
[test_streams_autoplay.html]
[test_streams_element_capture.html]
skip-if = e10s && os == 'win' # Bug 1065881 - Crash on child process shutdown in ShadowLayerForwarder::InWorkerThread
[test_streams_element_capture_createObjectURL.html]
[test_streams_element_capture_playback.html]
[test_streams_element_capture_reset.html]

View File

@ -97,9 +97,9 @@ function startTest(test, token) {
// This handler completes a start and stop of recording and verifies
// respective media recorder state.
var canPlayThrough = function() {
element.removeEventListener('canplaythrough', canPlayThrough, false);
element.onloadedmetadata = function () {
element.onloadedmetadata = null;
element.play();
mediaRecorder.start();
is(mediaRecorder.state, 'recording', 'Media recorder should be recording');
is(mediaRecorder.stream, element.stream,
@ -112,8 +112,7 @@ function startTest(test, token) {
'Media recorder stream = element stream post recording');
};
element.addEventListener('canplaythrough', canPlayThrough, false);
element.play();
element.preload = "metadata";
}
manager.runTests(gMediaRecorderTests, startTest);

View File

@ -84,24 +84,18 @@ function startTest(test, token) {
}
};
element.oncanplaythrough = function () {
element.oncanplaythrough = null;
// If content has ended, skip the test
if (element.ended) {
ok(true, 'ended fired before canplaythrough, skipping test');
manager.finished(token);
} else {
// If content hasn't ended, start recording
mediaRecorder.start();
is(mediaRecorder.state, 'recording',
'Media recorder should be recording');
is(mediaRecorder.stream, element.stream,
'Media recorder stream = element stream at the start of recording');
// Recording will automatically stop when the stream ends.
}
}
element.preload = "metadata";
element.play();
element.onloadedmetadata = function () {
element.onloadedmetadata = null;
mediaRecorder.start();
is(mediaRecorder.state, 'recording',
'Media recorder should be recording');
is(mediaRecorder.stream, element.stream,
'Media recorder stream = element stream at the start of recording');
element.play();
}
}
manager.runTests(gMediaRecorderTests, startTest);

View File

@ -54,15 +54,17 @@ function startTest(test, token) {
ok(false, 'Unexpected warning fired');
}
element.oncanplaythrough = function () {
element.oncanplaythrough = null;
element.preload = "metadata";
element.onloadedmetadata = function () {
element.onloadedmetadata = null;
element.play();
for (var i = 0; i < mExpectStopCount; i++) {
mediaRecorder.start(1000);
mediaRecorder.stop();
}
}
element.play();
}
manager.runTests(gMediaRecorderTests, startTest);

View File

@ -17,17 +17,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=495319
var manager = new MediaTestManager;
function timeupdate(e) {
var v = e.target;
v._timeupdateCount++;
ok(v.gotEnded == 0, v._name + " - shouldn't get timeupdate after ended");
}
function ended(e) {
var v = e.target;
++v.gotEnded;
ok(v._timeupdateCount > 0, v._name + " - should see at least one timeupdate: " + v.currentTime);
v._finished = true;
++v.counter["ended"];
is(v.counter["ended"], 1, v._name + " should see ended only once");
ok(v.counter["timeupdate"] > 0, v._name + " should see at least one timeupdate: " + v.currentTime);
// Rest event counters for we don't allow events after ended.
eventsToLog.forEach(function(e) {
v.counter[e] = 0;
});
// Finish the test after 500ms. We shouldn't receive any timeupdate events
// after the ended event, so this gives time for any pending timeupdate events
// to fire so we can ensure we don't regress behaviour.
@ -39,10 +39,9 @@ function ended(e) {
// invoked when it's removed from a document), and we don't want those
// confusing the test results.
v.removeEventListener("ended", ended, false);
v.removeEventListener("timeupdate", timeupdate, false);
for (var i = 0; i < eventsToLog.length; ++i) {
v.removeEventListener(eventsToLog[i], logEvent, false);
}
eventsToLog.forEach(function(e) {
v.removeEventListener(e, logEvent, false);
});
removeNodeAndSource(v);
manager.finished(v.token);
},
@ -50,17 +49,14 @@ function ended(e) {
}
var eventsToLog = ["play", "canplay", "canplaythrough", "loadstart", "loadedmetadata",
"loadeddata", "playing", "progress", "timeupdate", "ended", "suspend", "error", "stalled", "emptied", "abort",
"loadeddata", "playing", "timeupdate", "error", "stalled", "emptied", "abort",
"waiting", "pause"];
function logEvent(event) {
if (event.target.gotEnded > (event.type == "ended" ? 1 : 0)) {
if (event.target.currentSrc.slice(-9) == "seek.webm" && event.type == "stalled") {
todo(false, event.target.currentSrc + " got unexpected stalled after ended (bug 760770)");
} else {
ok(false, event.target.currentSrc + " got unexpected " + event.type + " after ended");
}
} else {
info(event.target.currentSrc + " got " + event.type);
var v = event.target;
++v.counter[event.type];
if (v.counter["ended"] > 0) {
is(v.counter[event.type], 0, v._name + " got unexpected " + event.type + " after ended");
}
}
@ -71,14 +67,15 @@ function startTest(test, token) {
manager.started(token);
v.src = test.name;
v._name = test.name;
v._timeupdateCount = 0;
v._finished = false;
v.gotEnded = 0;
// Keep how many events received for each event type.
v.counter = {};
eventsToLog.forEach(function(e) {
v.addEventListener(e, logEvent, false);
v.counter[e] = 0;
});
v.addEventListener("ended", ended, false);
v.addEventListener("timeupdate", timeupdate, false);
for (var i = 0; i < eventsToLog.length; ++i) {
v.addEventListener(eventsToLog[i], logEvent, false);
}
v.counter["ended"] = 0;
document.body.appendChild(v);
v.play();
}

View File

@ -411,7 +411,8 @@ PicoCallbackRunnable::OnCancel()
NS_INTERFACE_MAP_BEGIN(nsPicoService)
NS_INTERFACE_MAP_ENTRY(nsISpeechService)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISpeechService)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsPicoService)
@ -427,10 +428,6 @@ nsPicoService::nsPicoService()
, mTaResource(nullptr)
, mPicoMemArea(nullptr)
{
DebugOnly<nsresult> rv = NS_NewNamedThread("Pico Worker", getter_AddRefs(mThread));
MOZ_ASSERT(NS_SUCCEEDED(rv));
rv = mThread->Dispatch(NS_NewRunnableMethod(this, &nsPicoService::Init), NS_DISPATCH_NORMAL);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
nsPicoService::~nsPicoService()
@ -447,6 +444,20 @@ nsPicoService::~nsPicoService()
UnloadEngine();
}
// nsIObserver
NS_IMETHODIMP
nsPicoService::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE(!strcmp(aTopic, "profile-after-change"), NS_ERROR_UNEXPECTED);
DebugOnly<nsresult> rv = NS_NewNamedThread("Pico Worker", getter_AddRefs(mThread));
MOZ_ASSERT(NS_SUCCEEDED(rv));
return mThread->Dispatch(
NS_NewRunnableMethod(this, &nsPicoService::Init), NS_DISPATCH_NORMAL);
}
// nsISpeechService
NS_IMETHODIMP

View File

@ -10,6 +10,7 @@
#include "mozilla/Mutex.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "nsIObserver.h"
#include "nsIThread.h"
#include "nsISpeechService.h"
#include "nsRefPtrHashtable.h"
@ -26,7 +27,8 @@ typedef void* pico_System;
typedef void* pico_Resource;
typedef void* pico_Engine;
class nsPicoService : public nsISpeechService
class nsPicoService : public nsIObserver,
public nsISpeechService
{
friend class PicoCallbackRunnable;
friend class PicoInitRunnable;
@ -34,6 +36,7 @@ class nsPicoService : public nsISpeechService
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISPEECHSERVICE
NS_DECL_NSIOBSERVER
nsPicoService();

View File

@ -2702,7 +2702,6 @@ XULDocument::LoadOverlayInternal(nsIURI* aURI, bool aIsDynamic,
NodePrincipal(),
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
nsIContentPolicy::TYPE_OTHER,
nullptr, // aChannelPolicy
group);
if (NS_SUCCEEDED(rv)) {

View File

@ -67,7 +67,7 @@ static RedirEntry kRedirMap[] = {
nsIAboutModule::ALLOW_SCRIPT },
{ "networking", "chrome://global/content/aboutNetworking.xhtml",
nsIAboutModule::ALLOW_SCRIPT },
{ "webrtc", "chrome://global/content/aboutWebrtc.xhtml",
{ "webrtc", "chrome://global/content/aboutwebrtc/aboutWebrtc.xhtml",
nsIAboutModule::ALLOW_SCRIPT },
// about:srcdoc is unresolvable by specification. It is included here
// because the security manager would disallow srcdoc iframes otherwise.

View File

@ -168,7 +168,6 @@
#endif
#include "nsContentUtils.h"
#include "nsIChannelPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsILoadInfo.h"
#include "nsSandboxFlags.h"
@ -10158,27 +10157,7 @@ nsDocShell::DoURILoad(nsIURI * aURI,
loadFlags |= nsIChannel::LOAD_BACKGROUND;
}
// check for Content Security Policy to pass along with the
// new channel we are creating
nsCOMPtr<nsIChannelPolicy> channelPolicy;
if (IsFrame()) {
// check the parent docshell for a CSP
nsCOMPtr<nsIContentSecurityPolicy> csp;
nsCOMPtr<nsIDocShellTreeItem> parentItem;
GetSameTypeParent(getter_AddRefs(parentItem));
if (parentItem) {
nsCOMPtr<nsIDocument> doc = parentItem->GetDocument();
if (doc) {
rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
channelPolicy->SetContentSecurityPolicy(csp);
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_SUBDOCUMENT);
}
}
}
// Only allow view-source scheme in top-level docshells. view-source is
// the only scheme to which this applies at the moment due to potential
// timing attacks to read data from cross-origin iframes. If this widens
@ -10247,7 +10226,6 @@ nsDocShell::DoURILoad(nsIURI * aURI,
requestingPrincipal,
securityFlags,
aContentPolicyType,
channelPolicy,
nullptr, // loadGroup
static_cast<nsIInterfaceRequestor*>(this),
loadFlags);

View File

@ -131,9 +131,6 @@ this.DOMApplicationRegistry = {
APPS_IPC_MSG_NAMES.forEach((aMsgName) => {
this.cpmm.removeMessageListener(aMsgName, this);
});
this.cpmm.sendAsyncMessage("Webapps:UnregisterForMessages",
APPS_IPC_MSG_NAMES)
},
receiveMessage: function receiveMessage(aMessage) {

View File

@ -67,7 +67,6 @@
#include "mozIApplication.h"
#include "WidgetUtils.h"
#include "mozIThirdPartyUtil.h"
#include "nsChannelPolicy.h"
#ifdef MOZ_MEDIA_NAVIGATOR
#include "MediaManager.h"
@ -1056,26 +1055,11 @@ Navigator::SendBeacon(const nsAString& aUrl,
}
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIChannelPolicy> channelPolicy;
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = principal->GetCsp(getter_AddRefs(csp));
if (NS_FAILED(rv)) {
aRv.Throw(NS_ERROR_FAILURE);
return false;
}
if (csp) {
channelPolicy = do_CreateInstance(NSCHANNELPOLICY_CONTRACTID);
channelPolicy->SetContentSecurityPolicy(csp);
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_BEACON);
}
rv = NS_NewChannel(getter_AddRefs(channel),
uri,
doc,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_BEACON,
channelPolicy);
nsIContentPolicy::TYPE_BEACON);
if (NS_FAILED(rv)) {
aRv.Throw(rv);

View File

@ -75,7 +75,7 @@ public:
void Delete(const nsAString& aName);
void Stringify(nsString& aRetval)
void Stringify(nsString& aRetval) const
{
Serialize(aRetval);
}

View File

@ -62,3 +62,4 @@ MSG_DEF(MSG_PERMISSION_DENIED_TO_PASS_ARG, 1, "Permission denied to pass cross-o
MSG_DEF(MSG_MISSING_REQUIRED_DICTIONARY_MEMBER, 1, "Missing required {0}.")
MSG_DEF(MSG_INVALID_REQUEST_METHOD, 1, "Invalid request method {0}.")
MSG_DEF(MSG_REQUEST_BODY_CONSUMED_ERROR, 0, "Request body has already been consumed.")
MSG_DEF(MSG_RESPONSE_INVALID_STATUSTEXT_ERROR, 0, "Response statusText may not contain newline or carriage return.")

View File

@ -83,6 +83,7 @@ let SSL_ERROR_BAD_CERT_DOMAIN = (SSL_ERROR_BASE + 12);
let MOZILLA_PKIX_ERROR_BASE = Ci.nsINSSErrorsService.MOZILLA_PKIX_ERROR_BASE;
let MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY = (MOZILLA_PKIX_ERROR_BASE + 1);
let MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA = (MOZILLA_PKIX_ERROR_BASE + 3);
function getErrorClass(errorCode) {
let NSPRCode = -1 * NS_ERROR_GET_CODE(errorCode);
@ -96,6 +97,7 @@ function getErrorClass(errorCode) {
case SEC_ERROR_EXPIRED_CERTIFICATE:
case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
case MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY:
case MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA:
return Ci.nsINSSErrorsService.ERROR_CLASS_BAD_CERT;
default:
return Ci.nsINSSErrorsService.ERROR_CLASS_SSL_PROTOCOL;

View File

@ -1022,8 +1022,10 @@ CanvasRenderingContext2D::Redraw(const mgfx::Rect &r)
void
CanvasRenderingContext2D::DidRefresh()
{
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
if (glue) {
if (IsTargetValid() && SkiaGLTex()) {
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
MOZ_ASSERT(glue);
auto gl = glue->GetGLContext();
gl->FlushIfHeavyGLCallsSinceLastFlush();
}
@ -4823,6 +4825,14 @@ CanvasRenderingContext2D::CreateImageData(JSContext* cx,
static uint8_t g2DContextLayerUserData;
uint32_t
CanvasRenderingContext2D::SkiaGLTex() const
{
MOZ_ASSERT(IsTargetValid());
return (uint32_t)(uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE);
}
already_AddRefed<CanvasLayer>
CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer *aOldLayer,
@ -4854,9 +4864,11 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
CanvasLayer::Data data;
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
GLuint skiaGLTex = (GLuint)(uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE);
if (glue && skiaGLTex) {
GLuint skiaGLTex = SkiaGLTex();
if (skiaGLTex) {
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
MOZ_ASSERT(glue);
data.mGLContext = glue->GetGLContext();
data.mFrontbufferGLTex = skiaGLTex;
} else {
@ -4898,11 +4910,14 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
data.mSize = nsIntSize(mWidth, mHeight);
data.mHasAlpha = !mOpaque;
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
GLuint skiaGLTex = (GLuint)(uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE);
if (glue && skiaGLTex) {
GLuint skiaGLTex = SkiaGLTex();
if (skiaGLTex) {
canvasLayer->SetPreTransactionCallback(
CanvasRenderingContext2DUserData::PreTransactionCallback, userData);
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
MOZ_ASSERT(glue);
data.mGLContext = glue->GetGLContext();
data.mFrontbufferGLTex = skiaGLTex;
} else {

View File

@ -698,7 +698,9 @@ protected:
/**
* Check if the target is valid after calling EnsureTarget.
*/
bool IsTargetValid() { return mTarget != sErrorTarget && mTarget != nullptr; }
bool IsTargetValid() const {
return mTarget != sErrorTarget && mTarget != nullptr;
}
/**
* Returns the surface format this canvas should be allocated using. Takes
@ -764,6 +766,8 @@ protected:
// sErrorTarget.
mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget;
uint32_t SkiaGLTex() const;
/**
* Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
* Redraw is called, reset to false when Render is called.

View File

@ -351,6 +351,8 @@ WebGL2Context::GetTexParameterInternal(const TexTarget& target, GLenum pname)
{
switch (pname) {
case LOCAL_GL_TEXTURE_IMMUTABLE_FORMAT:
case LOCAL_GL_TEXTURE_BASE_LEVEL:
case LOCAL_GL_TEXTURE_MAX_LEVEL:
{
GLint i = 0;
gl->fGetTexParameteriv(target.get(), pname, &i);

View File

@ -922,7 +922,7 @@ WebGLContext::GenerateMipmap(GLenum rawTarget)
const TexImageTarget imageTarget = (target == LOCAL_GL_TEXTURE_2D)
? LOCAL_GL_TEXTURE_2D
: LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
if (!tex->HasImageInfoAt(imageTarget, 0))
if (!tex->HasImageInfoAt(imageTarget, tex->GetBaseMipmapLevel()))
{
return ErrorInvalidOperation("generateMipmap: Level zero of texture is not defined.");
}
@ -1510,6 +1510,19 @@ void WebGLContext::TexParameter_base(GLenum rawTarget, GLenum pname,
bool paramValueInvalid = false;
switch (pname) {
case LOCAL_GL_TEXTURE_BASE_LEVEL:
case LOCAL_GL_TEXTURE_MAX_LEVEL:
if (!IsWebGL2())
return ErrorInvalidEnumInfo("texParameter: pname", pname);
if (intParam < 0) {
paramValueInvalid = true;
break;
}
if (pname == LOCAL_GL_TEXTURE_BASE_LEVEL)
tex->SetBaseMipmapLevel(intParam);
else
tex->SetMaxMipmapLevel(intParam);
break;
case LOCAL_GL_TEXTURE_MIN_FILTER:
switch (intParam) {
case LOCAL_GL_NEAREST:

View File

@ -186,6 +186,10 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
gl->fGetIntegerv(pname, &val);
return JS::NumberValue(uint32_t(val));
}
case LOCAL_GL_TEXTURE_BINDING_3D: {
return WebGLObjectAsJSValue(cx, mBound3DTextures[mActiveTexture].get(), rv);
}
}
}

View File

@ -219,6 +219,13 @@ bool WebGLContext::ValidateTextureTargetEnum(GLenum target, const char *info)
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_CUBE_MAP:
return true;
case LOCAL_GL_TEXTURE_3D: {
const bool isValid = IsWebGL2();
if (!isValid) {
ErrorInvalidEnumInfo(info, target);
}
return isValid;
}
default:
ErrorInvalidEnumInfo(info, target);
return false;

View File

@ -33,6 +33,8 @@ WebGLTexture::WebGLTexture(WebGLContext *context)
, mMaxLevelWithCustomImages(0)
, mHaveGeneratedMipmap(false)
, mImmutable(false)
, mBaseMipmapLevel(0)
, mMaxMipmapLevel(1000)
, mFakeBlackStatus(WebGLTextureFakeBlackStatus::IncompleteTexture)
{
mContext->MakeContextCurrent();
@ -62,22 +64,8 @@ WebGLTexture::MemoryUsage() const {
return 0;
size_t result = 0;
for(size_t face = 0; face < mFacesCount; face++) {
if (mHaveGeneratedMipmap) {
size_t level0MemoryUsage = ImageInfoAtFace(face, 0).MemoryUsage();
// Each mipmap level is 1/(2^d) the size of the previous level,
// where d is 2 or 3 depending on whether the images are 2D or 3D
// 1 + x + x^2 + ... = 1/(1-x)
// for x = 1/(2^2), we get 1/(1-1/4) = 4/3
// for x = 1/(2^3), we get 1/(1-1/8) = 8/7
size_t allLevelsMemoryUsage =
mTarget == LOCAL_GL_TEXTURE_3D
? level0MemoryUsage * 8 / 7
: level0MemoryUsage * 4 / 3;
result += allLevelsMemoryUsage;
} else {
for(size_t level = 0; level <= mMaxLevelWithCustomImages; level++)
result += ImageInfoAtFace(face, level).MemoryUsage();
}
for(size_t level = 0; level <= mMaxLevelWithCustomImages; level++)
result += ImageInfoAtFace(face, level).MemoryUsage();
}
return result;
}
@ -88,15 +76,24 @@ WebGLTexture::DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImage
if (mHaveGeneratedMipmap)
return true;
if (GetMaxMipmapLevel() < GetBaseMipmapLevel())
return false;
// We want a copy here so we can modify it temporarily.
ImageInfo expected = ImageInfoAt(texImageTarget, 0);
ImageInfo expected = ImageInfoAt(texImageTarget, GetBaseMipmapLevel());
// checks if custom level>0 images are all defined up to the highest level defined
// and have the expected dimensions
for (size_t level = 0; level <= mMaxLevelWithCustomImages; ++level) {
for (size_t level = GetBaseMipmapLevel(); level <= GetMaxMipmapLevel(); ++level) {
const ImageInfo& actual = ImageInfoAt(texImageTarget, level);
if (actual != expected)
return false;
// Check the raw value here, not the clamped one, since we don't want
// to terminate early if there aren't enough levels defined.
if (level == mMaxMipmapLevel)
return true;
expected.mWidth = std::max(1, expected.mWidth / 2);
expected.mHeight = std::max(1, expected.mHeight / 2);
expected.mDepth = std::max(1, expected.mDepth / 2);
@ -185,7 +182,7 @@ WebGLTexture::SetCustomMipmap() {
// since we were in GeneratedMipmap mode, we know that the level 0 images all have the same info,
// and are power-of-two.
ImageInfo imageInfo = ImageInfoAtFace(0, 0);
ImageInfo imageInfo = ImageInfoAtFace(0, GetBaseMipmapLevel());
NS_ASSERTION(mContext->IsWebGL2() || imageInfo.IsPowerOfTwo(),
"this texture is NPOT, so how could GenerateMipmap() ever accept it?");
@ -198,7 +195,7 @@ WebGLTexture::SetCustomMipmap() {
EnsureMaxLevelWithCustomImagesAtLeast(maxLevel);
for (size_t level = 1; level <= maxLevel; ++level) {
for (size_t level = GetBaseMipmapLevel() + 1; level <= GetMaxMipmapLevel(); ++level) {
imageInfo.mWidth = std::max(imageInfo.mWidth / 2, 1);
imageInfo.mHeight = std::max(imageInfo.mHeight / 2, 1);
imageInfo.mDepth = std::max(imageInfo.mDepth / 2, 1);
@ -223,7 +220,7 @@ WebGLTexture::IsMipmapComplete() const {
MOZ_ASSERT(mTarget == LOCAL_GL_TEXTURE_2D ||
mTarget == LOCAL_GL_TEXTURE_3D);
if (!ImageInfoAtFace(0, 0).IsPositive())
if (!ImageInfoAtFace(0, GetBaseMipmapLevel()).IsPositive())
return false;
if (mHaveGeneratedMipmap)
return true;
@ -262,7 +259,7 @@ WebGLTexture::ResolvedFakeBlackStatus() {
// See 3.8.2 Shader Execution in the OpenGL ES 2.0.24 spec.
for (size_t face = 0; face < mFacesCount; ++face) {
if (ImageInfoAtFace(face, 0).mImageDataStatus == WebGLImageDataStatus::NoImageData) {
if (ImageInfoAtFace(face, GetBaseMipmapLevel()).mImageDataStatus == WebGLImageDataStatus::NoImageData) {
// In case of undefined texture image, we don't print any message because this is a very common
// and often legitimate case (asynchronous texture loading).
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;

View File

@ -213,6 +213,9 @@ protected:
bool mHaveGeneratedMipmap; // set by generateMipmap
bool mImmutable; // set by texStorage*
size_t mBaseMipmapLevel; // set by texParameter (defaults to 0)
size_t mMaxMipmapLevel; // set by texParameter (defaults to 1000)
WebGLTextureFakeBlackStatus mFakeBlackStatus;
void EnsureMaxLevelWithCustomImagesAtLeast(size_t aMaxLevelWithCustomImages) {
@ -283,6 +286,17 @@ public:
bool IsImmutable() const { return mImmutable; }
void SetImmutable() { mImmutable = true; }
void SetBaseMipmapLevel(unsigned level) { mBaseMipmapLevel = level; }
void SetMaxMipmapLevel(unsigned level) { mMaxMipmapLevel = level; }
size_t GetBaseMipmapLevel() const {
// Clamp to [0, levels - 1]
return std::min(mBaseMipmapLevel, mMaxLevelWithCustomImages);
}
size_t GetMaxMipmapLevel() const {
// Clamp to [base, levels - 1]
return std::min(mMaxMipmapLevel, mMaxLevelWithCustomImages);
}
size_t MaxLevelWithCustomImages() const { return mMaxLevelWithCustomImages; }
// Returns the current fake-black-status, except if it was Unknown,

View File

@ -395,7 +395,12 @@ CryptoKey::PublicKeyFromSpki(CryptoBuffer& aKeyData,
}
}
return SECKEY_ExtractPublicKey(spki.get());
ScopedSECKEYPublicKey tmp(SECKEY_ExtractPublicKey(spki.get()));
if (!tmp.get() || !PublicKeyValid(tmp.get())) {
return nullptr;
}
return SECKEY_CopyPublicKey(tmp);
}
nsresult
@ -843,6 +848,10 @@ CryptoKey::PublicKeyFromJwk(const JsonWebKey& aJwk,
}
key->u.ec.publicValue = *point;
if (!PublicKeyValid(key)) {
return nullptr;
}
return SECKEY_CopyPublicKey(key);
}
@ -881,6 +890,26 @@ CryptoKey::PublicKeyToJwk(SECKEYPublicKey* aPubKey,
}
}
bool
CryptoKey::PublicKeyValid(SECKEYPublicKey* aPubKey)
{
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
if (!slot.get()) {
return false;
}
// This assumes that NSS checks the validity of a public key when
// it is imported into a PKCS#11 module, and returns CK_INVALID_HANDLE
// if it is invalid.
CK_OBJECT_HANDLE id = PK11_ImportPublicKey(slot, aPubKey, PR_FALSE);
if (id == CK_INVALID_HANDLE) {
return false;
}
SECStatus rv = PK11_DestroyObject(slot, id);
return (rv == SECSuccess);
}
bool
CryptoKey::WriteStructuredClone(JSStructuredCloneWriter* aWriter) const
{

View File

@ -171,6 +171,8 @@ public:
JsonWebKey& aRetVal,
const nsNSSShutDownPreventionLock& /*proofOfLock*/);
static bool PublicKeyValid(SECKEYPublicKey* aPubKey);
// Structured clone methods use these to clone keys
bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const;
bool ReadStructuredClone(JSStructuredCloneReader* aReader);

View File

@ -27,6 +27,7 @@
#define WEBCRYPTO_ALG_RSASSA_PKCS1 "RSASSA-PKCS1-v1_5"
#define WEBCRYPTO_ALG_RSA_OAEP "RSA-OAEP"
#define WEBCRYPTO_ALG_ECDH "ECDH"
#define WEBCRYPTO_ALG_ECDSA "ECDSA"
// WebCrypto key formats
#define WEBCRYPTO_KEY_FORMAT_RAW "raw"
@ -84,6 +85,9 @@
#define JWK_ALG_RSA_OAEP_256 "RSA-OAEP-256"
#define JWK_ALG_RSA_OAEP_384 "RSA-OAEP-384"
#define JWK_ALG_RSA_OAEP_512 "RSA-OAEP-512"
#define JWK_ALG_ECDSA_P_256 "ES256"
#define JWK_ALG_ECDSA_P_384 "ES384"
#define JWK_ALG_ECDSA_P_521 "ES521"
// JWK usages
#define JWK_USE_ENC "enc"
@ -225,6 +229,8 @@ NormalizeToken(const nsString& aName, nsString& aDest)
aDest.AssignLiteral(WEBCRYPTO_ALG_RSA_OAEP);
} else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_ECDH)) {
aDest.AssignLiteral(WEBCRYPTO_ALG_ECDH);
} else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_ECDSA)) {
aDest.AssignLiteral(WEBCRYPTO_ALG_ECDSA);
// Named curve values
} else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P256)) {
aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P256);

View File

@ -66,7 +66,8 @@ enum TelemetryAlgorithm {
// Later additions
TA_AES_KW = 19,
TA_ECDH = 20,
TA_PBKDF2 = 21
TA_PBKDF2 = 21,
TA_ECDSA = 22,
};
// Convenience functions for extracting / converting information
@ -782,10 +783,9 @@ public:
mMgfMechanism = CKG_MGF1_SHA384; break;
case CKM_SHA512:
mMgfMechanism = CKG_MGF1_SHA512; break;
default: {
default:
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return;
}
}
}
@ -955,49 +955,97 @@ private:
}
};
class RsassaPkcs1Task : public WebCryptoTask
class AsymmetricSignVerifyTask : public WebCryptoTask
{
public:
RsassaPkcs1Task(JSContext* aCx, const ObjectOrString& aAlgorithm,
CryptoKey& aKey,
const CryptoOperationData& aSignature,
const CryptoOperationData& aData,
bool aSign)
AsymmetricSignVerifyTask(JSContext* aCx,
const ObjectOrString& aAlgorithm,
CryptoKey& aKey,
const CryptoOperationData& aSignature,
const CryptoOperationData& aData,
bool aSign)
: mOidTag(SEC_OID_UNKNOWN)
, mPrivKey(aKey.GetPrivateKey())
, mPubKey(aKey.GetPublicKey())
, mSign(aSign)
, mVerified(false)
, mEcdsa(false)
{
Telemetry::Accumulate(Telemetry::WEBCRYPTO_ALG, TA_RSASSA_PKCS1);
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_RSASSA_PKCS1);
ATTEMPT_BUFFER_INIT(mData, aData);
if (!aSign) {
ATTEMPT_BUFFER_INIT(mSignature, aSignature);
}
// Look up the SECOidTag based on the KeyAlgorithm
// static_cast is safe because we only get here if the algorithm name
// is RSASSA-PKCS1-v1_5, and that only happens if we've constructed
// an RsaHashedKeyAlgorithm
CK_MECHANISM_TYPE mech;
mech = KeyAlgorithmProxy::GetMechanism(aKey.Algorithm().mRsa.mHash);
nsString algName;
mEarlyRv = GetAlgorithmName(aCx, aAlgorithm, algName);
if (NS_FAILED(mEarlyRv)) {
return;
}
switch (mech) {
case CKM_SHA_1:
mOidTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; break;
case CKM_SHA256:
mOidTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; break;
case CKM_SHA384:
mOidTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; break;
case CKM_SHA512:
mOidTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; break;
default: {
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
// Look up the SECOidTag
if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
mEcdsa = false;
Telemetry::Accumulate(Telemetry::WEBCRYPTO_ALG, TA_RSASSA_PKCS1);
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_RSASSA_PKCS1);
// For RSA, the hash name comes from the key algorithm
nsString hashName = aKey.Algorithm().mRsa.mHash.mName;
switch (MapAlgorithmNameToMechanism(hashName)) {
case CKM_SHA_1:
mOidTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; break;
case CKM_SHA256:
mOidTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; break;
case CKM_SHA384:
mOidTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; break;
case CKM_SHA512:
mOidTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; break;
default:
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return;
}
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA)) {
mEcdsa = true;
Telemetry::Accumulate(Telemetry::WEBCRYPTO_ALG, TA_ECDSA);
CHECK_KEY_ALGORITHM(aKey.Algorithm(), WEBCRYPTO_ALG_ECDSA);
// For ECDSA, the hash name comes from the algorithm parameter
RootedDictionary<EcdsaParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
nsString hashName;
mEarlyRv = GetAlgorithmName(aCx, params.mHash, hashName);
if (NS_FAILED(mEarlyRv)) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
CK_MECHANISM_TYPE hashMechanism = MapAlgorithmNameToMechanism(hashName);
if (hashMechanism == UNKNOWN_CK_MECHANISM) {
mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
return;
}
switch (hashMechanism) {
case CKM_SHA_1:
mOidTag = SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE; break;
case CKM_SHA256:
mOidTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE; break;
case CKM_SHA384:
mOidTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE; break;
case CKM_SHA512:
mOidTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE; break;
default:
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return;
}
} else {
// This shouldn't happen; CreateSignVerifyTask shouldn't create
// one of these unless it's for the above algorithms.
MOZ_ASSERT(false);
}
// Check that we have the appropriate key
@ -1015,6 +1063,7 @@ private:
CryptoBuffer mData;
bool mSign;
bool mVerified;
bool mEcdsa;
virtual nsresult DoCrypto() MOZ_OVERRIDE
{
@ -1022,44 +1071,53 @@ private:
if (mSign) {
ScopedSECItem signature((SECItem*) PORT_Alloc(sizeof(SECItem)));
ScopedSGNContext ctx(SGN_NewContext(mOidTag, mPrivKey));
if (!ctx) {
if (!signature.get() || !ctx.get()) {
return NS_ERROR_DOM_OPERATION_ERR;
}
rv = MapSECStatus(SGN_Begin(ctx));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
rv = MapSECStatus(SEC_SignData(signature, mData.Elements(),
mData.Length(), mPrivKey, mOidTag));
rv = MapSECStatus(SGN_Update(ctx, mData.Elements(), mData.Length()));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
rv = MapSECStatus(SGN_End(ctx, signature));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
ATTEMPT_BUFFER_ASSIGN(mSignature, signature);
} else {
ScopedSECItem signature(mSignature.ToSECItem());
if (!signature) {
return NS_ERROR_DOM_UNKNOWN_ERR;
}
ScopedVFYContext ctx(VFY_CreateContext(mPubKey, signature,
mOidTag, nullptr));
if (!ctx) {
int err = PORT_GetError();
if (err == SEC_ERROR_BAD_SIGNATURE) {
mVerified = false;
return NS_OK;
if (mEcdsa) {
// DER-decode the signature
int signatureLength = PK11_SignatureLen(mPrivKey);
ScopedSECItem rawSignature(DSAU_DecodeDerSigToLen(signature.get(),
signatureLength));
if (!rawSignature.get()) {
return NS_ERROR_DOM_OPERATION_ERR;
}
return NS_ERROR_DOM_OPERATION_ERR;
ATTEMPT_BUFFER_ASSIGN(mSignature, rawSignature);
} else {
ATTEMPT_BUFFER_ASSIGN(mSignature, signature);
}
rv = MapSECStatus(VFY_Begin(ctx));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
} else {
ScopedSECItem signature;
rv = MapSECStatus(VFY_Update(ctx, mData.Elements(), mData.Length()));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
if (mEcdsa) {
// DER-encode the signature
ScopedSECItem rawSignature(mSignature.ToSECItem());
if (!rawSignature.get()) {
return NS_ERROR_DOM_UNKNOWN_ERR;
}
rv = MapSECStatus(VFY_End(ctx));
signature = (SECItem*) PORT_Alloc(sizeof(SECItem));
if (!signature.get()) {
return NS_ERROR_DOM_UNKNOWN_ERR;
}
rv = MapSECStatus(DSAU_EncodeDerSigWithLen(signature, rawSignature,
rawSignature->len));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
} else {
signature = mSignature.ToSECItem();
if (!signature) {
return NS_ERROR_DOM_UNKNOWN_ERR;
}
}
rv = MapSECStatus(VFY_VerifyData(mData.Elements(), mData.Length(),
mPubKey, signature, mOidTag, nullptr));
mVerified = NS_SUCCEEDED(rv);
}
@ -1661,12 +1719,23 @@ private:
virtual nsresult AfterCrypto() MOZ_OVERRIDE
{
// Check permissions for the requested operation
if (mKey->GetKeyType() == CryptoKey::PRIVATE &&
mKey->HasUsageOtherThan(CryptoKey::DERIVEBITS | CryptoKey::DERIVEKEY)) {
return NS_ERROR_DOM_DATA_ERR;
uint32_t privateAllowedUsages = 0, publicAllowedUsages = 0;
if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
privateAllowedUsages = CryptoKey::DERIVEBITS | CryptoKey::DERIVEKEY;
publicAllowedUsages = CryptoKey::DERIVEBITS | CryptoKey::DERIVEKEY;
} else if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA)) {
privateAllowedUsages = CryptoKey::SIGN;
publicAllowedUsages = CryptoKey::VERIFY;
}
// Check permissions for the requested operation
if ((mKey->GetKeyType() == CryptoKey::PRIVATE &&
mKey->HasUsageOtherThan(privateAllowedUsages)) ||
(mKey->GetKeyType() == CryptoKey::PUBLIC &&
mKey->HasUsageOtherThan(publicAllowedUsages))) {
return NS_ERROR_DOM_DATA_ERR;
}
mKey->Algorithm().MakeEc(mAlgName, mNamedCurve);
if (mDataIsJwk && !JwkCompatible(mJwk, mKey)) {
@ -1991,7 +2060,8 @@ public:
mEarlyRv = NS_ERROR_DOM_INVALID_ACCESS_ERR;
return;
}
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA)) {
RootedDictionary<EcKeyGenParams> params(aCx);
mEarlyRv = Coerce(aCx, params, aAlgorithm);
if (NS_FAILED(mEarlyRv)) {
@ -2014,7 +2084,8 @@ public:
}
// Set key usages.
if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA)) {
privateAllowedUsages = CryptoKey::SIGN;
publicAllowedUsages = CryptoKey::VERIFY;
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
@ -2048,7 +2119,7 @@ public:
}
// If no usages ended up being allowed, DataError
if (!mKeyPair.mPrivateKey.get()->HasAnyUsage() ||
if (!mKeyPair.mPublicKey.get()->HasAnyUsage() &&
!mKeyPair.mPrivateKey.get()->HasAnyUsage()) {
mEarlyRv = NS_ERROR_DOM_DATA_ERR;
return;
@ -2176,10 +2247,9 @@ public:
case CKM_SHA256: mHashOidTag = SEC_OID_HMAC_SHA256; break;
case CKM_SHA384: mHashOidTag = SEC_OID_HMAC_SHA384; break;
case CKM_SHA512: mHashOidTag = SEC_OID_HMAC_SHA512; break;
default: {
default:
mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
return;
}
}
ATTEMPT_BUFFER_INIT(mSalt, params.mSalt)
@ -2544,8 +2614,10 @@ WebCryptoTask::CreateSignVerifyTask(JSContext* aCx,
if (algName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
return new HmacTask(aCx, aAlgorithm, aKey, aSignature, aData, aSign);
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
return new RsassaPkcs1Task(aCx, aAlgorithm, aKey, aSignature, aData, aSign);
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA)) {
return new AsymmetricSignVerifyTask(aCx, aAlgorithm, aKey, aSignature,
aData, aSign);
}
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
@ -2618,7 +2690,8 @@ WebCryptoTask::CreateImportKeyTask(JSContext* aCx,
algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
return new ImportRsaKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
aExtractable, aKeyUsages);
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA)) {
return new ImportEcKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
aExtractable, aKeyUsages);
} else {
@ -2694,7 +2767,8 @@ WebCryptoTask::CreateGenerateKeyTask(JSContext* aCx,
return new GenerateSymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
} else if (algName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
algName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP) ||
algName.EqualsASCII(WEBCRYPTO_ALG_ECDH)) {
algName.EqualsASCII(WEBCRYPTO_ALG_ECDH) ||
algName.EqualsASCII(WEBCRYPTO_ALG_ECDSA)) {
return new GenerateAsymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
} else {
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);

View File

@ -608,4 +608,54 @@ tv = {
x: "XOe4bjsyZgQD5jcS7wmY3q4QJ_rsPBvp92-TTf61jpg",
}
},
// NIST ECDSA test vectors
// http://csrc.nist.gov/groups/STM/cavp/index.html
ecdsa_verify: {
pub_jwk: {
"kty": "EC",
"crv": "P-521",
// 0061387fd6b95914e885f912edfbb5fb274655027f216c4091ca83e19336740fd8
// 1aedfe047f51b42bdf68161121013e0d55b117a14e4303f926c8debb77a7fdaad1
"x": "AGE4f9a5WRTohfkS7fu1-ydGVQJ_IWxAkcqD4ZM2dA_Y" +
"Gu3-BH9RtCvfaBYRIQE-DVWxF6FOQwP5Jsjeu3en_arR",
// 00e7d0c75c38626e895ca21526b9f9fdf84dcecb93f2b233390550d2b1463b7ee3
// f58df7346435ff0434199583c97c665a97f12f706f2357da4b40288def888e59e6
"y": "AOfQx1w4Ym6JXKIVJrn5_fhNzsuT8rIzOQVQ0rFGO37j" +
"9Y33NGQ1_wQ0GZWDyXxmWpfxL3BvI1faS0Aoje-Ijlnm",
},
"data": util.hex2abv(
"9ecd500c60e701404922e58ab20cc002651fdee7cbc9336adda33e4c1088fab1" +
"964ecb7904dc6856865d6c8e15041ccf2d5ac302e99d346ff2f686531d255216" +
"78d4fd3f76bbf2c893d246cb4d7693792fe18172108146853103a51f824acc62" +
"1cb7311d2463c3361ea707254f2b052bc22cb8012873dcbb95bf1a5cc53ab89f"
),
"sig": util.hex2abv(
"004de826ea704ad10bc0f7538af8a3843f284f55c8b946af9235af5af74f2b76e0" +
"99e4bc72fd79d28a380f8d4b4c919ac290d248c37983ba05aea42e2dd79fdd33e8" +
"0087488c859a96fea266ea13bf6d114c429b163be97a57559086edb64aed4a1859" +
"4b46fb9efc7fd25d8b2de8f09ca0587f54bd287299f47b2ff124aac566e8ee3b43"
),
// Same as "sig", but with the last few octets set to 0
"sig_tampered": util.hex2abv(
"004de826ea704ad10bc0f7538af8a3843f284f55c8b946af9235af5af74f2b76e0" +
"99e4bc72fd79d28a380f8d4b4c919ac290d248c37983ba05aea42e2dd79fdd33e8" +
"0087488c859a96fea266ea13bf6d114c429b163be97a57559086edb64aed4a1859" +
"4b46fb9efc7fd25d8b2de8f09ca0587f54bd287299f47b2ff124aac56600000000"
)
},
ecdsa_bad: {
pub_jwk: {
"kty": "EC",
"crv": "P-521",
"x": "BhOH_WuVkU6IX5Eu37tfsnRlUCfyFsQJHKg-GTNnQP2B" +
"rt_gR_UbQr32gWESEBPg1VsRehTkMD-SbI3rt3p_2q0B",
"y": "AUNouOdGgHsraPNhXNeNdhpGTd15GPyN9R0iWWL98ePc" +
"JD4mUQD/DsEzNZ4zLkTdSa/Y5fOP6GEzVzQy0zwC+goD"
}
}
}

View File

@ -1308,6 +1308,32 @@ TestArray.addTest(
doCheckRSASSA().then(error(that), complete(that));
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Test that we reject generating keys without any usage",
function() {
var that = this;
var alg = {
name: "RSA-OAEP",
hash: "SHA-256",
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01])
};
function generateKey(usages) {
return crypto.subtle.generateKey(alg, false, usages);
}
generateKey(["encrypt", "decrypt"]).then(function () {
return generateKey(["encrypt"]);
}).then(function () {
return generateKey(["decrypt"]);
}).then(function () {
return generateKey(["sign"])
}, error(that)).then(error(that), complete(that));
}
);
/*]]>*/</script>
</head>

View File

@ -0,0 +1,162 @@
<!DOCTYPE html>
<html>
<head>
<title>WebCrypto Test Suite</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href="./test_WebCrypto.css"/>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<!-- Utilities for manipulating ABVs -->
<script src="util.js"></script>
<!-- A simple wrapper around IndexedDB -->
<script src="simpledb.js"></script>
<!-- Test vectors drawn from the literature -->
<script src="./test-vectors.js"></script>
<!-- General testing framework -->
<script src="./test-array.js"></script>
<script>/*<![CDATA[*/
"use strict";
// -----------------------------------------------------------------------------
TestArray.addTest(
"Generate an ECDSA key for named curve P-256",
function() {
var that = this;
var alg = { name: "ECDSA", namedCurve: "P-256" };
crypto.subtle.generateKey(alg, false, ["sign", "verify"]).then(
complete(that, function(x) {
return exists(x.publicKey) &&
(x.publicKey.algorithm.name == alg.name) &&
(x.publicKey.algorithm.namedCurve == alg.namedCurve) &&
(x.publicKey.type == "public") &&
x.publicKey.extractable &&
(x.publicKey.usages.length == 1) &&
(x.publicKey.usages[0] == "verify") &&
exists(x.privateKey) &&
(x.privateKey.algorithm.name == alg.name) &&
(x.privateKey.algorithm.namedCurve == alg.namedCurve) &&
(x.privateKey.type == "private") &&
!x.privateKey.extractable &&
(x.privateKey.usages.length == 1) &&
(x.privateKey.usages[0] == "sign")
}),
error(that)
);
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"ECDSA JWK import and verify a known-good signature",
function() {
var that = this;
var alg = { name: "ECDSA", namedCurve: "P-256", hash: "SHA-256" };
function doVerify(x) {
return crypto.subtle.verify(alg, x, tv.ecdsa_verify.sig, tv.ecdsa_verify.data);
}
crypto.subtle.importKey("jwk", tv.ecdsa_verify.pub_jwk, alg, true, ["verify"])
.then(doVerify)
.then(complete(that), error(that))
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"ECDSA JWK import and reject a known-bad signature",
function() {
var that = this;
var alg = { name: "ECDSA", namedCurve: "P-256", hash: "SHA-256" };
function doVerify(x) {
return crypto.subtle.verify(alg, x, tv.ecdsa_verify.sig_tampered,
tv.ecdsa_verify.data);
}
crypto.subtle.importKey("jwk", tv.ecdsa_verify.pub_jwk, alg, true, ["verify"])
.then(doVerify)
.then(complete(that, x => !x), error(that))
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"ECDSA sign/verify round-trip",
function() {
var that = this;
var alg = { name: "ECDSA", namedCurve: "P-521", hash: "SHA-512" };
var pubKey;
function doSign(keyPair) {
pubKey = keyPair.publicKey;
return crypto.subtle.sign(alg, keyPair.privateKey, tv.ecdsa_verify.data);
}
function doVerify(sig) {
return crypto.subtle.verify(alg, pubKey, sig, tv.ecdsa_verify.data);
}
crypto.subtle.generateKey(alg, true, ["sign", "verify"])
.then(doSign)
.then(doVerify)
.then(complete(that), error(that))
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Verify that ECDSA import fails with a known-bad public key",
function() {
var that = this;
var alg = { name: "ECDSA", namedCurve: "P-256", hash: "SHA-256" };
function doVerify(x) {
return crypto.subtle.verify(alg, x, tv.ecdsa_verify.sig, tv.ecdsa_verify.data);
}
crypto.subtle.importKey("jwk", tv.ecdsa_bad.pub_jwk, alg, true, ["verify"])
.then(error(that), complete(that))
}
);
/*]]>*/</script>
</head>
<body>
<div id="content">
<div id="head">
<b>Web</b>Crypto<br>
</div>
<div id="start" onclick="start();">RUN ALL</div>
<div id="resultDiv" class="content">
Summary:
<span class="pass"><span id="passN">0</span> passed, </span>
<span class="fail"><span id="failN">0</span> failed, </span>
<span class="pending"><span id="pendingN">0</span> pending.</span>
<br/>
<br/>
<table id="results">
<tr>
<th>Test</th>
<th>Result</th>
<th>Time</th>
</tr>
</table>
</div>
<div id="foot"></div>
</div>
</body>
</html>

View File

@ -76,6 +76,7 @@ Event::ConstructorInit(EventTarget* aOwner,
}
mPrivateDataDuplicated = false;
mWantsPopupControlCheck = false;
if (aEvent) {
mEvent = aEvent;
@ -655,12 +656,20 @@ PopupAllowedForEvent(const char *eventName)
// static
PopupControlState
Event::GetEventPopupControlState(WidgetEvent* aEvent)
Event::GetEventPopupControlState(WidgetEvent* aEvent, nsIDOMEvent* aDOMEvent)
{
// generally if an event handler is running, new windows are disallowed.
// check for exceptions:
PopupControlState abuse = openAbused;
if (aDOMEvent && aDOMEvent->InternalDOMEvent()->GetWantsPopupControlCheck()) {
nsAutoString type;
aDOMEvent->GetType(type);
if (PopupAllowedForEvent(NS_ConvertUTF16toUTF8(type).get())) {
return openAllowed;
}
}
switch(aEvent->mClass) {
case eBasicEventClass:
// For these following events only allow popups if they're

View File

@ -30,6 +30,7 @@ namespace dom {
class EventTarget;
class ErrorEvent;
class ProgressEvent;
class WantsPopupControlCheck;
// Dummy class so we can cast through it to get from nsISupports to
// Event subclasses with only two non-ambiguous static casts.
@ -113,7 +114,8 @@ public:
// Returns true if the event should be trusted.
bool Init(EventTarget* aGlobal);
static PopupControlState GetEventPopupControlState(WidgetEvent* aEvent);
static PopupControlState GetEventPopupControlState(WidgetEvent* aEvent,
nsIDOMEvent* aDOMEvent = nullptr);
static void PopupAllowedEventsChanged();
@ -235,6 +237,17 @@ protected:
void SetEventType(const nsAString& aEventTypeArg);
already_AddRefed<nsIContent> GetTargetFromFrame();
friend class WantsPopupControlCheck;
void SetWantsPopupControlCheck(bool aCheck)
{
mWantsPopupControlCheck = aCheck;
}
bool GetWantsPopupControlCheck()
{
return IsTrusted() && mWantsPopupControlCheck;
}
/**
* IsChrome() returns true if aCx is chrome context or the event is created
* in chrome's thread. Otherwise, false.
@ -248,6 +261,28 @@ protected:
bool mEventIsInternal;
bool mPrivateDataDuplicated;
bool mIsMainThreadEvent;
// True when popup control check should rely on event.type, not
// WidgetEvent.message.
bool mWantsPopupControlCheck;
};
class MOZ_STACK_CLASS WantsPopupControlCheck
{
public:
WantsPopupControlCheck(nsIDOMEvent* aEvent) : mEvent(aEvent->InternalDOMEvent())
{
mOriginalWantsPopupControlCheck = mEvent->GetWantsPopupControlCheck();
mEvent->SetWantsPopupControlCheck(mEvent->IsTrusted());
}
~WantsPopupControlCheck()
{
mEvent->SetWantsPopupControlCheck(mOriginalWantsPopupControlCheck);
}
private:
Event* mEvent;
bool mOriginalWantsPopupControlCheck;
};
} // namespace dom

View File

@ -976,7 +976,7 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
nsAutoTObserverArray<Listener, 2>::EndLimitedIterator iter(mListeners);
Maybe<nsAutoPopupStatePusher> popupStatePusher;
if (mIsMainThreadELM) {
popupStatePusher.emplace(Event::GetEventPopupControlState(aEvent));
popupStatePusher.emplace(Event::GetEventPopupControlState(aEvent, *aDOMEvent));
}
bool hasListener = false;

View File

@ -944,16 +944,21 @@ EventStateManager::ExecuteAccessKey(nsTArray<uint32_t>& aAccessCharCodes,
return false;
}
bool
EventStateManager::GetAccessKeyLabelPrefix(nsAString& aPrefix)
// static
void
EventStateManager::GetAccessKeyLabelPrefix(Element* aElement, nsAString& aPrefix)
{
aPrefix.Truncate();
nsAutoString separator, modifierText;
nsContentUtils::GetModifierSeparatorText(separator);
nsCOMPtr<nsISupports> container = mPresContext->GetContainerWeak();
nsCOMPtr<nsISupports> container = aElement->OwnerDoc()->GetDocShell();
int32_t modifierMask = GetAccessModifierMaskFor(container);
if (modifierMask == -1) {
return;
}
if (modifierMask & NS_MODIFIER_CONTROL) {
nsContentUtils::GetControlText(modifierText);
aPrefix.Append(modifierText + separator);
@ -974,7 +979,6 @@ EventStateManager::GetAccessKeyLabelPrefix(nsAString& aPrefix)
nsContentUtils::GetShiftText(modifierText);
aPrefix.Append(modifierText + separator);
}
return !aPrefix.IsEmpty();
}
void

View File

@ -40,6 +40,7 @@ class WheelTransaction;
namespace dom {
class DataTransfer;
class Element;
class TabParent;
} // namespace dom
@ -169,7 +170,7 @@ public:
*/
uint32_t GetRegisteredAccessKey(nsIContent* aContent);
bool GetAccessKeyLabelPrefix(nsAString& aPrefix);
static void GetAccessKeyLabelPrefix(dom::Element* aElement, nsAString& aPrefix);
nsresult SetCursor(int32_t aCursor, imgIContainer* aContainer,
bool aHaveHotspot, float aHotspotX, float aHotspotY,

View File

@ -22,6 +22,7 @@ skip-if = buildapp == 'b2g'
skip-if = buildapp == 'b2g'
[test_bug288392.html]
[test_bug299673-1.html]
[test_bug1037990.html]
[test_bug299673-2.html]
[test_bug322588.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage

View File

@ -0,0 +1,61 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1037990
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1037990</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1037990">Mozilla Bug 1037990</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script type="application/javascript">
/** Test for Bug 1037990 **/
var pre, node, detachedAccess, attachedAcess;
node = document.createElement('a');
node.href = 'http://example.org';
node.accessKey = 'e';
detachedAccess = node.accessKeyLabel;
info('[window.document] detached: ' + detachedAccess);
document.body.appendChild(node);
attachedAcess = node.accessKeyLabel;
info('[window.document] attached: ' + attachedAcess);
is(detachedAccess, attachedAcess, "Both values are same for the window.document");
var parser=new DOMParser();
var xmlDoc=parser.parseFromString("<root></root>","text/xml");
var nn = xmlDoc.createElementNS('http://www.w3.org/1999/xhtml','a');
nn.setAttribute('accesskey','t')
detachedAccess = nn.accessKeyLabel;
info('[xmlDoc] detached: ' + detachedAccess);
var root = xmlDoc.getElementsByTagName('root')[0];
root.appendChild(nn);
attachedAcess = nn.accessKeyLabel;
info('[xmlDoc] attached: ' + attachedAcess);
is(detachedAccess, attachedAcess, "Both values are same for the xmlDoc");
var myDoc = new Document();
var newnode = myDoc.createElementNS('http://www.w3.org/1999/xhtml','a');
newnode.href = 'http://example.org';
newnode.accessKey = 'f';
detachedAccess = newnode.accessKeyLabel;
info('[new document] detached: ' + detachedAccess);
myDoc.appendChild(newnode);
attachedAcess = newnode.accessKeyLabel;
info('[new document] attached: ' + attachedAcess);
is(detachedAccess, attachedAcess, "Both values are same for the new Document()");
</script>
</body>
</html>

View File

@ -6,95 +6,360 @@
#include "Fetch.h"
#include "nsIStringStream.h"
#include "nsIUnicodeDecoder.h"
#include "nsIUnicodeEncoder.h"
#include "nsDOMString.h"
#include "nsNetUtil.h"
#include "nsStreamUtils.h"
#include "nsStringStream.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/EncodingUtils.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/Headers.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/Request.h"
#include "mozilla/dom/Response.h"
#include "mozilla/dom/URLSearchParams.h"
namespace mozilla {
namespace dom {
namespace {
nsresult
ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams& aBodyInit,
ExtractFromArrayBuffer(const ArrayBuffer& aBuffer,
nsIInputStream** aStream)
{
aBuffer.ComputeLengthAndData();
//XXXnsm reinterpret_cast<> is used in DOMParser, should be ok.
return NS_NewByteInputStream(aStream,
reinterpret_cast<char*>(aBuffer.Data()),
aBuffer.Length(), NS_ASSIGNMENT_COPY);
}
nsresult
ExtractFromArrayBufferView(const ArrayBufferView& aBuffer,
nsIInputStream** aStream)
{
aBuffer.ComputeLengthAndData();
//XXXnsm reinterpret_cast<> is used in DOMParser, should be ok.
return NS_NewByteInputStream(aStream,
reinterpret_cast<char*>(aBuffer.Data()),
aBuffer.Length(), NS_ASSIGNMENT_COPY);
}
nsresult
ExtractFromBlob(const File& aFile, nsIInputStream** aStream,
nsCString& aContentType)
{
nsRefPtr<FileImpl> impl = aFile.Impl();
nsresult rv = impl->GetInternalStream(aStream);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsString type;
impl->GetType(type);
aContentType = NS_ConvertUTF16toUTF8(type);
return NS_OK;
}
nsresult
ExtractFromScalarValueString(const nsString& aStr,
nsIInputStream** aStream,
nsCString& aContentType)
{
nsCOMPtr<nsIUnicodeEncoder> encoder = EncodingUtils::EncoderForEncoding("UTF-8");
if (!encoder) {
return NS_ERROR_OUT_OF_MEMORY;
}
int32_t destBufferLen;
nsresult rv = encoder->GetMaxLength(aStr.get(), aStr.Length(), &destBufferLen);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCString encoded;
if (!encoded.SetCapacity(destBufferLen, fallible_t())) {
return NS_ERROR_OUT_OF_MEMORY;
}
char* destBuffer = encoded.BeginWriting();
int32_t srcLen = (int32_t) aStr.Length();
int32_t outLen = destBufferLen;
rv = encoder->Convert(aStr.get(), &srcLen, destBuffer, &outLen);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(outLen <= destBufferLen);
encoded.SetLength(outLen);
aContentType = NS_LITERAL_CSTRING("text/plain;charset=UTF-8");
return NS_NewCStringInputStream(aStream, encoded);
}
nsresult
ExtractFromURLSearchParams(const URLSearchParams& aParams,
nsIInputStream** aStream,
nsCString& aContentType)
{
nsAutoString serialized;
aParams.Stringify(serialized);
aContentType = NS_LITERAL_CSTRING("application/x-www-form-urlencoded;charset=UTF-8");
return NS_NewStringInputStream(aStream, serialized);
}
}
nsresult
ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams& aBodyInit,
nsIInputStream** aStream,
nsCString& aContentType)
{
MOZ_ASSERT(aStream);
nsresult rv;
nsCOMPtr<nsIInputStream> byteStream;
if (aBodyInit.IsArrayBuffer()) {
const ArrayBuffer& buf = aBodyInit.GetAsArrayBuffer();
buf.ComputeLengthAndData();
//XXXnsm reinterpret_cast<> is used in DOMParser, should be ok.
rv = NS_NewByteInputStream(getter_AddRefs(byteStream),
reinterpret_cast<char*>(buf.Data()),
buf.Length(), NS_ASSIGNMENT_COPY);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return ExtractFromArrayBuffer(buf, aStream);
} else if (aBodyInit.IsArrayBufferView()) {
const ArrayBufferView& buf = aBodyInit.GetAsArrayBufferView();
buf.ComputeLengthAndData();
//XXXnsm reinterpret_cast<> is used in DOMParser, should be ok.
rv = NS_NewByteInputStream(getter_AddRefs(byteStream),
reinterpret_cast<char*>(buf.Data()),
buf.Length(), NS_ASSIGNMENT_COPY);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return ExtractFromArrayBufferView(buf, aStream);
} else if (aBodyInit.IsBlob()) {
const File& blob = aBodyInit.GetAsBlob();
return ExtractFromBlob(blob, aStream, aContentType);
} else if (aBodyInit.IsScalarValueString()) {
nsString str = aBodyInit.GetAsScalarValueString();
nsCOMPtr<nsIUnicodeEncoder> encoder = EncodingUtils::EncoderForEncoding("UTF-8");
if (!encoder) {
return NS_ERROR_OUT_OF_MEMORY;
}
int32_t destBufferLen;
rv = encoder->GetMaxLength(str.get(), str.Length(), &destBufferLen);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCString encoded;
if (!encoded.SetCapacity(destBufferLen, fallible_t())) {
return NS_ERROR_OUT_OF_MEMORY;
}
char* destBuffer = encoded.BeginWriting();
int32_t srcLen = (int32_t) str.Length();
int32_t outLen = destBufferLen;
rv = encoder->Convert(str.get(), &srcLen, destBuffer, &outLen);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(outLen <= destBufferLen);
encoded.SetLength(outLen);
rv = NS_NewCStringInputStream(getter_AddRefs(byteStream), encoded);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
aContentType = NS_LITERAL_CSTRING("text/plain;charset=UTF-8");
nsAutoString str;
str.Assign(aBodyInit.GetAsScalarValueString());
return ExtractFromScalarValueString(str, aStream, aContentType);
} else if (aBodyInit.IsURLSearchParams()) {
URLSearchParams& params = aBodyInit.GetAsURLSearchParams();
nsString serialized;
params.Stringify(serialized);
rv = NS_NewStringInputStream(getter_AddRefs(byteStream), serialized);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
aContentType = NS_LITERAL_CSTRING("application/x-www-form-urlencoded;charset=UTF-8");
return ExtractFromURLSearchParams(params, aStream, aContentType);
}
MOZ_ASSERT(byteStream);
byteStream.forget(aStream);
return NS_OK;
NS_NOTREACHED("Should never reach here");
return NS_ERROR_FAILURE;
}
nsresult
ExtractByteStreamFromBody(const ArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams& aBodyInit,
nsIInputStream** aStream,
nsCString& aContentType)
{
MOZ_ASSERT(aStream);
if (aBodyInit.IsArrayBuffer()) {
const ArrayBuffer& buf = aBodyInit.GetAsArrayBuffer();
return ExtractFromArrayBuffer(buf, aStream);
} else if (aBodyInit.IsArrayBufferView()) {
const ArrayBufferView& buf = aBodyInit.GetAsArrayBufferView();
return ExtractFromArrayBufferView(buf, aStream);
} else if (aBodyInit.IsBlob()) {
const File& blob = aBodyInit.GetAsBlob();
return ExtractFromBlob(blob, aStream, aContentType);
} else if (aBodyInit.IsScalarValueString()) {
nsAutoString str;
str.Assign(aBodyInit.GetAsScalarValueString());
return ExtractFromScalarValueString(str, aStream, aContentType);
} else if (aBodyInit.IsURLSearchParams()) {
URLSearchParams& params = aBodyInit.GetAsURLSearchParams();
return ExtractFromURLSearchParams(params, aStream, aContentType);
}
NS_NOTREACHED("Should never reach here");
return NS_ERROR_FAILURE;
}
namespace {
nsresult
DecodeUTF8(const nsCString& aBuffer, nsString& aDecoded)
{
nsCOMPtr<nsIUnicodeDecoder> decoder =
EncodingUtils::DecoderForEncoding("UTF-8");
if (!decoder) {
return NS_ERROR_FAILURE;
}
int32_t destBufferLen;
nsresult rv =
decoder->GetMaxLength(aBuffer.get(), aBuffer.Length(), &destBufferLen);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!aDecoded.SetCapacity(destBufferLen, fallible_t())) {
return NS_ERROR_OUT_OF_MEMORY;
}
char16_t* destBuffer = aDecoded.BeginWriting();
int32_t srcLen = (int32_t) aBuffer.Length();
int32_t outLen = destBufferLen;
rv = decoder->Convert(aBuffer.get(), &srcLen, destBuffer, &outLen);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(outLen <= destBufferLen);
aDecoded.SetLength(outLen);
return NS_OK;
}
}
template <class Derived>
already_AddRefed<Promise>
FetchBody<Derived>::ConsumeBody(ConsumeType aType, ErrorResult& aRv)
{
nsRefPtr<Promise> promise = Promise::Create(DerivedClass()->GetParentObject(), aRv);
if (aRv.Failed()) {
return nullptr;
}
if (BodyUsed()) {
aRv.ThrowTypeError(MSG_REQUEST_BODY_CONSUMED_ERROR);
return nullptr;
}
SetBodyUsed();
// While the spec says to do this asynchronously, all the body constructors
// right now only accept bodies whose streams are backed by an in-memory
// buffer that can be read without blocking. So I think this is fine.
nsCOMPtr<nsIInputStream> stream;
DerivedClass()->GetBody(getter_AddRefs(stream));
if (!stream) {
aRv = NS_NewByteInputStream(getter_AddRefs(stream), "", 0,
NS_ASSIGNMENT_COPY);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
}
AutoJSAPI api;
api.Init(DerivedClass()->GetParentObject());
JSContext* cx = api.cx();
// We can make this assertion because for now we only support memory backed
// structures for the body argument for a Request.
MOZ_ASSERT(NS_InputStreamIsBuffered(stream));
nsCString buffer;
uint64_t len;
aRv = stream->Available(&len);
if (aRv.Failed()) {
return nullptr;
}
aRv = NS_ReadInputStreamToString(stream, buffer, len);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
buffer.SetLength(len);
switch (aType) {
case CONSUME_ARRAYBUFFER: {
JS::Rooted<JSObject*> arrayBuffer(cx);
arrayBuffer =
ArrayBuffer::Create(cx, buffer.Length(),
reinterpret_cast<const uint8_t*>(buffer.get()));
JS::Rooted<JS::Value> val(cx);
val.setObjectOrNull(arrayBuffer);
promise->MaybeResolve(cx, val);
return promise.forget();
}
case CONSUME_BLOB: {
// XXXnsm it is actually possible to avoid these duplicate allocations
// for the Blob case by having the Blob adopt the stream's memory
// directly, but I've not added a special case for now.
//
// FIXME(nsm): Use nsContentUtils::CreateBlobBuffer once blobs have been fixed on
// workers.
uint32_t blobLen = buffer.Length();
void* blobData = moz_malloc(blobLen);
nsRefPtr<File> blob;
if (blobData) {
memcpy(blobData, buffer.BeginReading(), blobLen);
blob = File::CreateMemoryFile(DerivedClass()->GetParentObject(), blobData, blobLen,
NS_ConvertUTF8toUTF16(mMimeType));
} else {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}
promise->MaybeResolve(blob);
return promise.forget();
}
case CONSUME_JSON: {
nsAutoString decoded;
aRv = DecodeUTF8(buffer, decoded);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
JS::Rooted<JS::Value> json(cx);
if (!JS_ParseJSON(cx, decoded.get(), decoded.Length(), &json)) {
JS::Rooted<JS::Value> exn(cx);
if (JS_GetPendingException(cx, &exn)) {
JS_ClearPendingException(cx);
promise->MaybeReject(cx, exn);
}
}
promise->MaybeResolve(cx, json);
return promise.forget();
}
case CONSUME_TEXT: {
nsAutoString decoded;
aRv = DecodeUTF8(buffer, decoded);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
promise->MaybeResolve(decoded);
return promise.forget();
}
}
NS_NOTREACHED("Unexpected consume body type");
// Silence warnings.
return nullptr;
}
template
already_AddRefed<Promise>
FetchBody<Request>::ConsumeBody(ConsumeType aType, ErrorResult& aRv);
template
already_AddRefed<Promise>
FetchBody<Response>::ConsumeBody(ConsumeType aType, ErrorResult& aRv);
template <class Derived>
void
FetchBody<Derived>::SetMimeType(ErrorResult& aRv)
{
// Extract mime type.
nsTArray<nsCString> contentTypeValues;
MOZ_ASSERT(DerivedClass()->GetInternalHeaders());
DerivedClass()->GetInternalHeaders()->GetAll(NS_LITERAL_CSTRING("Content-Type"), contentTypeValues, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
// HTTP ABNF states Content-Type may have only one value.
// This is from the "parse a header value" of the fetch spec.
if (contentTypeValues.Length() == 1) {
mMimeType = contentTypeValues[0];
ToLowerCase(mMimeType);
}
}
template
void
FetchBody<Request>::SetMimeType(ErrorResult& aRv);
template
void
FetchBody<Response>::SetMimeType(ErrorResult& aRv);
} // namespace dom
} // namespace mozilla

View File

@ -13,16 +13,93 @@ class nsIInputStream;
namespace mozilla {
namespace dom {
class Promise;
/*
* Creates an nsIInputStream based on the fetch specifications 'extract a byte
* stream algorithm' - http://fetch.spec.whatwg.org/#concept-bodyinit-extract.
* Stores content type in out param aContentType.
*/
nsresult
ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams& aBodyInit,
ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams& aBodyInit,
nsIInputStream** aStream,
nsCString& aContentType);
/*
* Non-owning version.
*/
nsresult
ExtractByteStreamFromBody(const ArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams& aBodyInit,
nsIInputStream** aStream,
nsCString& aContentType);
template <class Derived>
class FetchBody {
public:
bool
BodyUsed() { return mBodyUsed; }
already_AddRefed<Promise>
ArrayBuffer(ErrorResult& aRv)
{
return ConsumeBody(CONSUME_ARRAYBUFFER, aRv);
}
already_AddRefed<Promise>
Blob(ErrorResult& aRv)
{
return ConsumeBody(CONSUME_BLOB, aRv);
}
already_AddRefed<Promise>
Json(ErrorResult& aRv)
{
return ConsumeBody(CONSUME_JSON, aRv);
}
already_AddRefed<Promise>
Text(ErrorResult& aRv)
{
return ConsumeBody(CONSUME_TEXT, aRv);
}
protected:
FetchBody()
: mBodyUsed(false)
{
}
void
SetBodyUsed()
{
mBodyUsed = true;
}
void
SetMimeType(ErrorResult& aRv);
private:
enum ConsumeType
{
CONSUME_ARRAYBUFFER,
CONSUME_BLOB,
// FormData not supported right now,
CONSUME_JSON,
CONSUME_TEXT,
};
Derived*
DerivedClass() const
{
return static_cast<Derived*>(const_cast<FetchBody*>(this));
}
already_AddRefed<Promise>
ConsumeBody(ConsumeType aType, ErrorResult& aRv);
bool mBodyUsed;
nsCString mMimeType;
};
} // namespace dom
} // namespace mozilla

View File

@ -10,13 +10,6 @@
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/Preferences.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsContentUtils.h"
#include "nsDOMString.h"
#include "nsNetUtil.h"
#include "nsPIDOMWindow.h"
#include "nsReadableUtils.h"
namespace mozilla {
namespace dom {
@ -61,18 +54,19 @@ Headers::Constructor(const GlobalObject& aGlobal,
const Optional<HeadersOrByteStringSequenceSequenceOrByteStringMozMap>& aInit,
ErrorResult& aRv)
{
nsRefPtr<Headers> headers = new Headers(aGlobal.GetAsSupports());
nsRefPtr<InternalHeaders> ih = new InternalHeaders();
nsRefPtr<Headers> headers = new Headers(aGlobal.GetAsSupports(), ih);
if (!aInit.WasPassed()) {
return headers.forget();
}
if (aInit.Value().IsHeaders()) {
headers->Fill(aInit.Value().GetAsHeaders(), aRv);
ih->Fill(*aInit.Value().GetAsHeaders().mInternalHeaders, aRv);
} else if (aInit.Value().IsByteStringSequenceSequence()) {
headers->Fill(aInit.Value().GetAsByteStringSequenceSequence(), aRv);
ih->Fill(aInit.Value().GetAsByteStringSequenceSequence(), aRv);
} else if (aInit.Value().IsByteStringMozMap()) {
headers->Fill(aInit.Value().GetAsByteStringMozMap(), aRv);
ih->Fill(aInit.Value().GetAsByteStringMozMap(), aRv);
}
if (aRv.Failed()) {
@ -88,14 +82,15 @@ Headers::Constructor(const GlobalObject& aGlobal,
const OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap& aInit,
ErrorResult& aRv)
{
nsRefPtr<Headers> headers = new Headers(aGlobal.GetAsSupports());
nsRefPtr<InternalHeaders> ih = new InternalHeaders();
nsRefPtr<Headers> headers = new Headers(aGlobal.GetAsSupports(), ih);
if (aInit.IsHeaders()) {
headers->Fill(aInit.GetAsHeaders(), aRv);
ih->Fill(*(aInit.GetAsHeaders().get()->mInternalHeaders), aRv);
} else if (aInit.IsByteStringSequenceSequence()) {
headers->Fill(aInit.GetAsByteStringSequenceSequence(), aRv);
ih->Fill(aInit.GetAsByteStringSequenceSequence(), aRv);
} else if (aInit.IsByteStringMozMap()) {
headers->Fill(aInit.GetAsByteStringMozMap(), aRv);
ih->Fill(aInit.GetAsByteStringMozMap(), aRv);
}
if (NS_WARN_IF(aRv.Failed())) {
@ -105,153 +100,6 @@ Headers::Constructor(const GlobalObject& aGlobal,
return headers.forget();
}
Headers::Headers(const Headers& aOther)
: mOwner(aOther.mOwner)
, mGuard(aOther.mGuard)
{
ErrorResult result;
Fill(aOther, result);
MOZ_ASSERT(!result.Failed());
}
void
Headers::Append(const nsACString& aName, const nsACString& aValue,
ErrorResult& aRv)
{
nsAutoCString lowerName;
ToLowerCase(aName, lowerName);
if (IsInvalidMutableHeader(lowerName, &aValue, aRv)) {
return;
}
mList.AppendElement(Entry(lowerName, aValue));
}
void
Headers::Delete(const nsACString& aName, ErrorResult& aRv)
{
nsAutoCString lowerName;
ToLowerCase(aName, lowerName);
if (IsInvalidMutableHeader(lowerName, nullptr, aRv)) {
return;
}
// remove in reverse order to minimize copying
for (int32_t i = mList.Length() - 1; i >= 0; --i) {
if (lowerName == mList[i].mName) {
mList.RemoveElementAt(i);
}
}
}
void
Headers::Get(const nsACString& aName, nsCString& aValue, ErrorResult& aRv) const
{
nsAutoCString lowerName;
ToLowerCase(aName, lowerName);
if (IsInvalidName(lowerName, aRv)) {
return;
}
for (uint32_t i = 0; i < mList.Length(); ++i) {
if (lowerName == mList[i].mName) {
aValue = mList[i].mValue;
return;
}
}
// No value found, so return null to content
aValue.SetIsVoid(true);
}
void
Headers::GetAll(const nsACString& aName, nsTArray<nsCString>& aResults,
ErrorResult& aRv) const
{
nsAutoCString lowerName;
ToLowerCase(aName, lowerName);
if (IsInvalidName(lowerName, aRv)) {
return;
}
aResults.SetLength(0);
for (uint32_t i = 0; i < mList.Length(); ++i) {
if (lowerName == mList[i].mName) {
aResults.AppendElement(mList[i].mValue);
}
}
}
bool
Headers::Has(const nsACString& aName, ErrorResult& aRv) const
{
nsAutoCString lowerName;
ToLowerCase(aName, lowerName);
if (IsInvalidName(lowerName, aRv)) {
return false;
}
for (uint32_t i = 0; i < mList.Length(); ++i) {
if (lowerName == mList[i].mName) {
return true;
}
}
return false;
}
void
Headers::Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv)
{
nsAutoCString lowerName;
ToLowerCase(aName, lowerName);
if (IsInvalidMutableHeader(lowerName, &aValue, aRv)) {
return;
}
int32_t firstIndex = INT32_MAX;
// remove in reverse order to minimize copying
for (int32_t i = mList.Length() - 1; i >= 0; --i) {
if (lowerName == mList[i].mName) {
firstIndex = std::min(firstIndex, i);
mList.RemoveElementAt(i);
}
}
if (firstIndex < INT32_MAX) {
Entry* entry = mList.InsertElementAt(firstIndex);
entry->mName = lowerName;
entry->mValue = aValue;
} else {
mList.AppendElement(Entry(lowerName, aValue));
}
}
void
Headers::Clear()
{
mList.Clear();
}
void
Headers::SetGuard(HeadersGuardEnum aGuard, ErrorResult& aRv)
{
// Rather than re-validate all current headers, just require code to set
// this prior to populating the Headers object. Allow setting immutable
// late, though, as that is pretty much required to have a useful, immutable
// headers object.
if (aGuard != HeadersGuardEnum::Immutable && mList.Length() > 0) {
aRv.Throw(NS_ERROR_FAILURE);
}
mGuard = aGuard;
}
JSObject*
Headers::WrapObject(JSContext* aCx)
{
@ -261,109 +109,5 @@ Headers::WrapObject(JSContext* aCx)
Headers::~Headers()
{
}
// static
bool
Headers::IsSimpleHeader(const nsACString& aName, const nsACString* aValue)
{
// Note, we must allow a null content-type value here to support
// get("content-type"), but the IsInvalidValue() check will prevent null
// from being set or appended.
return aName.EqualsLiteral("accept") ||
aName.EqualsLiteral("accept-language") ||
aName.EqualsLiteral("content-language") ||
(aName.EqualsLiteral("content-type") &&
(!aValue || nsContentUtils::IsAllowedNonCorsContentType(*aValue)));
}
//static
bool
Headers::IsInvalidName(const nsACString& aName, ErrorResult& aRv)
{
if (!NS_IsValidHTTPToken(aName)) {
NS_ConvertUTF8toUTF16 label(aName);
aRv.ThrowTypeError(MSG_INVALID_HEADER_NAME, &label);
return true;
}
return false;
}
// static
bool
Headers::IsInvalidValue(const nsACString& aValue, ErrorResult& aRv)
{
if (!NS_IsReasonableHTTPHeaderValue(aValue)) {
NS_ConvertUTF8toUTF16 label(aValue);
aRv.ThrowTypeError(MSG_INVALID_HEADER_VALUE, &label);
return true;
}
return false;
}
bool
Headers::IsImmutable(ErrorResult& aRv) const
{
if (mGuard == HeadersGuardEnum::Immutable) {
aRv.ThrowTypeError(MSG_HEADERS_IMMUTABLE);
return true;
}
return false;
}
bool
Headers::IsForbiddenRequestHeader(const nsACString& aName) const
{
return mGuard == HeadersGuardEnum::Request &&
nsContentUtils::IsForbiddenRequestHeader(aName);
}
bool
Headers::IsForbiddenRequestNoCorsHeader(const nsACString& aName,
const nsACString* aValue) const
{
return mGuard == HeadersGuardEnum::Request_no_cors &&
!IsSimpleHeader(aName, aValue);
}
bool
Headers::IsForbiddenResponseHeader(const nsACString& aName) const
{
return mGuard == HeadersGuardEnum::Response &&
nsContentUtils::IsForbiddenResponseHeader(aName);
}
void
Headers::Fill(const Headers& aInit, ErrorResult& aRv)
{
const nsTArray<Entry>& list = aInit.mList;
for (uint32_t i = 0; i < list.Length() && !aRv.Failed(); ++i) {
const Entry& entry = list[i];
Append(entry.mName, entry.mValue, aRv);
}
}
void
Headers::Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& aRv)
{
for (uint32_t i = 0; i < aInit.Length() && !aRv.Failed(); ++i) {
const Sequence<nsCString>& tuple = aInit[i];
if (tuple.Length() != 2) {
aRv.ThrowTypeError(MSG_INVALID_HEADER_SEQUENCE);
return;
}
Append(tuple[0], tuple[1], aRv);
}
}
void
Headers::Fill(const MozMap<nsCString>& aInit, ErrorResult& aRv)
{
nsTArray<nsString> keys;
aInit.GetKeys(keys);
for (uint32_t i = 0; i < keys.Length() && !aRv.Failed(); ++i) {
Append(NS_ConvertUTF16toUTF8(keys[i]), aInit.Get(keys[i]), aRv);
}
}
} // namespace dom
} // namespace mozilla

View File

@ -13,6 +13,8 @@
#include "nsClassHashtable.h"
#include "nsWrapperCache.h"
#include "InternalHeaders.h"
class nsPIDOMWindow;
namespace mozilla {
@ -24,38 +26,34 @@ namespace dom {
template<typename T> class MozMap;
class HeadersOrByteStringSequenceSequenceOrByteStringMozMap;
/**
* This Headers class is only used to represent the content facing Headers
* object. It is actually backed by an InternalHeaders implementation. Gecko
* code should NEVER use this, except in the Request and Response
* implementations, where they must always be created from the backing
* InternalHeaders object.
*/
class Headers MOZ_FINAL : public nsISupports
, public nsWrapperCache
{
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Headers)
friend class Request;
friend class Response;
private:
struct Entry
{
Entry(const nsACString& aName, const nsACString& aValue)
: mName(aName)
, mValue(aValue)
{ }
Entry() { }
nsCString mName;
nsCString mValue;
};
nsCOMPtr<nsISupports> mOwner;
HeadersGuardEnum mGuard;
nsTArray<Entry> mList;
nsRefPtr<InternalHeaders> mInternalHeaders;
public:
explicit Headers(nsISupports* aOwner, HeadersGuardEnum aGuard = HeadersGuardEnum::None)
explicit Headers(nsISupports* aOwner, InternalHeaders* aInternalHeaders)
: mOwner(aOwner)
, mGuard(aGuard)
, mInternalHeaders(aInternalHeaders)
{
}
explicit Headers(const Headers& aOther);
explicit Headers(const Headers& aOther) MOZ_DELETE;
static bool PrefEnabled(JSContext* cx, JSObject* obj);
@ -70,56 +68,59 @@ public:
ErrorResult& aRv);
void Append(const nsACString& aName, const nsACString& aValue,
ErrorResult& aRv);
void Delete(const nsACString& aName, ErrorResult& aRv);
void Get(const nsACString& aName, nsCString& aValue, ErrorResult& aRv) const;
void GetAll(const nsACString& aName, nsTArray<nsCString>& aResults,
ErrorResult& aRv) const;
bool Has(const nsACString& aName, ErrorResult& aRv) const;
void Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv);
ErrorResult& aRv)
{
mInternalHeaders->Append(aName, aValue, aRv);
}
void Clear();
void Delete(const nsACString& aName, ErrorResult& aRv)
{
mInternalHeaders->Delete(aName, aRv);
}
void Get(const nsACString& aName, nsCString& aValue, ErrorResult& aRv) const
{
mInternalHeaders->Get(aName, aValue, aRv);
}
void GetAll(const nsACString& aName, nsTArray<nsCString>& aResults,
ErrorResult& aRv) const
{
mInternalHeaders->GetAll(aName, aResults, aRv);
}
bool Has(const nsACString& aName, ErrorResult& aRv) const
{
return mInternalHeaders->Has(aName, aRv);
}
void Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv)
{
mInternalHeaders->Set(aName, aValue, aRv);
}
// ChromeOnly
HeadersGuardEnum Guard() const { return mGuard; }
void SetGuard(HeadersGuardEnum aGuard, ErrorResult& aRv);
HeadersGuardEnum Guard() const
{
return mInternalHeaders->Guard();
}
void SetGuard(HeadersGuardEnum aGuard, ErrorResult& aRv)
{
mInternalHeaders->SetGuard(aGuard, aRv);
}
virtual JSObject* WrapObject(JSContext* aCx);
nsISupports* GetParentObject() const { return mOwner; }
void Fill(const Headers& aInit, ErrorResult& aRv);
private:
// Since Headers is also an nsISupports, the above constructor can
// accidentally be invoked as new Headers(Headers*[, implied None guard]) when
// the intention is to use the copy constructor. Explicitly disallow it.
Headers(Headers* aOther) MOZ_DELETE;
virtual ~Headers();
static bool IsSimpleHeader(const nsACString& aName,
const nsACString* aValue = nullptr);
static bool IsInvalidName(const nsACString& aName, ErrorResult& aRv);
static bool IsInvalidValue(const nsACString& aValue, ErrorResult& aRv);
bool IsImmutable(ErrorResult& aRv) const;
bool IsForbiddenRequestHeader(const nsACString& aName) const;
bool IsForbiddenRequestNoCorsHeader(const nsACString& aName,
const nsACString* aValue = nullptr) const;
bool IsForbiddenResponseHeader(const nsACString& aName) const;
bool IsInvalidMutableHeader(const nsACString& aName,
const nsACString* aValue,
ErrorResult& aRv) const
InternalHeaders*
GetInternalHeaders() const
{
return IsInvalidName(aName, aRv) ||
(aValue && IsInvalidValue(*aValue, aRv)) ||
IsImmutable(aRv) ||
IsForbiddenRequestHeader(aName) ||
IsForbiddenRequestNoCorsHeader(aName, aValue) ||
IsForbiddenResponseHeader(aName);
return mInternalHeaders;
}
void Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& aRv);
void Fill(const MozMap<nsCString>& aInit, ErrorResult& aRv);
};
} // namespace dom

View File

@ -0,0 +1,272 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/InternalHeaders.h"
#include "mozilla/ErrorResult.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsContentUtils.h"
#include "nsNetUtil.h"
#include "nsReadableUtils.h"
namespace mozilla {
namespace dom {
void
InternalHeaders::Append(const nsACString& aName, const nsACString& aValue,
ErrorResult& aRv)
{
nsAutoCString lowerName;
ToLowerCase(aName, lowerName);
if (IsInvalidMutableHeader(lowerName, aValue, aRv)) {
return;
}
mList.AppendElement(Entry(lowerName, aValue));
}
void
InternalHeaders::Delete(const nsACString& aName, ErrorResult& aRv)
{
nsAutoCString lowerName;
ToLowerCase(aName, lowerName);
if (IsInvalidMutableHeader(lowerName, aRv)) {
return;
}
// remove in reverse order to minimize copying
for (int32_t i = mList.Length() - 1; i >= 0; --i) {
if (lowerName == mList[i].mName) {
mList.RemoveElementAt(i);
}
}
}
void
InternalHeaders::Get(const nsACString& aName, nsCString& aValue, ErrorResult& aRv) const
{
nsAutoCString lowerName;
ToLowerCase(aName, lowerName);
if (IsInvalidName(lowerName, aRv)) {
return;
}
for (uint32_t i = 0; i < mList.Length(); ++i) {
if (lowerName == mList[i].mName) {
aValue = mList[i].mValue;
return;
}
}
// No value found, so return null to content
aValue.SetIsVoid(true);
}
void
InternalHeaders::GetAll(const nsACString& aName, nsTArray<nsCString>& aResults,
ErrorResult& aRv) const
{
nsAutoCString lowerName;
ToLowerCase(aName, lowerName);
if (IsInvalidName(lowerName, aRv)) {
return;
}
aResults.SetLength(0);
for (uint32_t i = 0; i < mList.Length(); ++i) {
if (lowerName == mList[i].mName) {
aResults.AppendElement(mList[i].mValue);
}
}
}
bool
InternalHeaders::Has(const nsACString& aName, ErrorResult& aRv) const
{
nsAutoCString lowerName;
ToLowerCase(aName, lowerName);
if (IsInvalidName(lowerName, aRv)) {
return false;
}
for (uint32_t i = 0; i < mList.Length(); ++i) {
if (lowerName == mList[i].mName) {
return true;
}
}
return false;
}
void
InternalHeaders::Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv)
{
nsAutoCString lowerName;
ToLowerCase(aName, lowerName);
if (IsInvalidMutableHeader(lowerName, aValue, aRv)) {
return;
}
int32_t firstIndex = INT32_MAX;
// remove in reverse order to minimize copying
for (int32_t i = mList.Length() - 1; i >= 0; --i) {
if (lowerName == mList[i].mName) {
firstIndex = std::min(firstIndex, i);
mList.RemoveElementAt(i);
}
}
if (firstIndex < INT32_MAX) {
Entry* entry = mList.InsertElementAt(firstIndex);
entry->mName = lowerName;
entry->mValue = aValue;
} else {
mList.AppendElement(Entry(lowerName, aValue));
}
}
void
InternalHeaders::Clear()
{
mList.Clear();
}
void
InternalHeaders::SetGuard(HeadersGuardEnum aGuard, ErrorResult& aRv)
{
// Rather than re-validate all current headers, just require code to set
// this prior to populating the InternalHeaders object. Allow setting immutable
// late, though, as that is pretty much required to have a useful, immutable
// headers object.
if (aGuard != HeadersGuardEnum::Immutable && mList.Length() > 0) {
aRv.Throw(NS_ERROR_FAILURE);
}
mGuard = aGuard;
}
InternalHeaders::~InternalHeaders()
{
}
// static
bool
InternalHeaders::IsSimpleHeader(const nsACString& aName, const nsACString& aValue)
{
// Note, we must allow a null content-type value here to support
// get("content-type"), but the IsInvalidValue() check will prevent null
// from being set or appended.
return aName.EqualsLiteral("accept") ||
aName.EqualsLiteral("accept-language") ||
aName.EqualsLiteral("content-language") ||
(aName.EqualsLiteral("content-type") &&
nsContentUtils::IsAllowedNonCorsContentType(aValue));
}
//static
bool
InternalHeaders::IsInvalidName(const nsACString& aName, ErrorResult& aRv)
{
if (!NS_IsValidHTTPToken(aName)) {
NS_ConvertUTF8toUTF16 label(aName);
aRv.ThrowTypeError(MSG_INVALID_HEADER_NAME, &label);
return true;
}
return false;
}
// static
bool
InternalHeaders::IsInvalidValue(const nsACString& aValue, ErrorResult& aRv)
{
if (!NS_IsReasonableHTTPHeaderValue(aValue)) {
NS_ConvertUTF8toUTF16 label(aValue);
aRv.ThrowTypeError(MSG_INVALID_HEADER_VALUE, &label);
return true;
}
return false;
}
bool
InternalHeaders::IsImmutable(ErrorResult& aRv) const
{
if (mGuard == HeadersGuardEnum::Immutable) {
aRv.ThrowTypeError(MSG_HEADERS_IMMUTABLE);
return true;
}
return false;
}
bool
InternalHeaders::IsForbiddenRequestHeader(const nsACString& aName) const
{
return mGuard == HeadersGuardEnum::Request &&
nsContentUtils::IsForbiddenRequestHeader(aName);
}
bool
InternalHeaders::IsForbiddenRequestNoCorsHeader(const nsACString& aName) const
{
return mGuard == HeadersGuardEnum::Request_no_cors &&
!IsSimpleHeader(aName, EmptyCString());
}
bool
InternalHeaders::IsForbiddenRequestNoCorsHeader(const nsACString& aName,
const nsACString& aValue) const
{
return mGuard == HeadersGuardEnum::Request_no_cors &&
!IsSimpleHeader(aName, aValue);
}
bool
InternalHeaders::IsForbiddenResponseHeader(const nsACString& aName) const
{
return mGuard == HeadersGuardEnum::Response &&
nsContentUtils::IsForbiddenResponseHeader(aName);
}
void
InternalHeaders::Fill(const InternalHeaders& aInit, ErrorResult& aRv)
{
const nsTArray<Entry>& list = aInit.mList;
for (uint32_t i = 0; i < list.Length() && !aRv.Failed(); ++i) {
const Entry& entry = list[i];
Append(entry.mName, entry.mValue, aRv);
}
}
void
InternalHeaders::Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& aRv)
{
for (uint32_t i = 0; i < aInit.Length() && !aRv.Failed(); ++i) {
const Sequence<nsCString>& tuple = aInit[i];
if (tuple.Length() != 2) {
aRv.ThrowTypeError(MSG_INVALID_HEADER_SEQUENCE);
return;
}
Append(tuple[0], tuple[1], aRv);
}
}
void
InternalHeaders::Fill(const MozMap<nsCString>& aInit, ErrorResult& aRv)
{
nsTArray<nsString> keys;
aInit.GetKeys(keys);
for (uint32_t i = 0; i < keys.Length() && !aRv.Failed(); ++i) {
Append(NS_ConvertUTF16toUTF8(keys[i]), aInit.Get(keys[i]), aRv);
}
}
} // namespace dom
} // namespace mozilla

116
dom/fetch/InternalHeaders.h Normal file
View File

@ -0,0 +1,116 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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_InternalHeaders_h
#define mozilla_dom_InternalHeaders_h
// needed for HeadersGuardEnum.
#include "mozilla/dom/HeadersBinding.h"
#include "mozilla/dom/UnionTypes.h"
#include "nsClassHashtable.h"
#include "nsWrapperCache.h"
class nsPIDOMWindow;
namespace mozilla {
class ErrorResult;
namespace dom {
template<typename T> class MozMap;
class HeadersOrByteStringSequenceSequenceOrByteStringMozMap;
class InternalHeaders MOZ_FINAL
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalHeaders)
private:
struct Entry
{
Entry(const nsACString& aName, const nsACString& aValue)
: mName(aName)
, mValue(aValue)
{ }
Entry() { }
nsCString mName;
nsCString mValue;
};
HeadersGuardEnum mGuard;
nsTArray<Entry> mList;
public:
explicit InternalHeaders(HeadersGuardEnum aGuard = HeadersGuardEnum::None)
: mGuard(aGuard)
{
}
explicit InternalHeaders(const InternalHeaders& aOther)
: mGuard(aOther.mGuard)
{
ErrorResult result;
Fill(aOther, result);
MOZ_ASSERT(!result.Failed());
}
void Append(const nsACString& aName, const nsACString& aValue,
ErrorResult& aRv);
void Delete(const nsACString& aName, ErrorResult& aRv);
void Get(const nsACString& aName, nsCString& aValue, ErrorResult& aRv) const;
void GetAll(const nsACString& aName, nsTArray<nsCString>& aResults,
ErrorResult& aRv) const;
bool Has(const nsACString& aName, ErrorResult& aRv) const;
void Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv);
void Clear();
HeadersGuardEnum Guard() const { return mGuard; }
void SetGuard(HeadersGuardEnum aGuard, ErrorResult& aRv);
void Fill(const InternalHeaders& aInit, ErrorResult& aRv);
void Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& aRv);
void Fill(const MozMap<nsCString>& aInit, ErrorResult& aRv);
private:
virtual ~InternalHeaders();
static bool IsSimpleHeader(const nsACString& aName,
const nsACString& aValue);
static bool IsInvalidName(const nsACString& aName, ErrorResult& aRv);
static bool IsInvalidValue(const nsACString& aValue, ErrorResult& aRv);
bool IsImmutable(ErrorResult& aRv) const;
bool IsForbiddenRequestHeader(const nsACString& aName) const;
bool IsForbiddenRequestNoCorsHeader(const nsACString& aName) const;
bool IsForbiddenRequestNoCorsHeader(const nsACString& aName,
const nsACString& aValue) const;
bool IsForbiddenResponseHeader(const nsACString& aName) const;
bool IsInvalidMutableHeader(const nsACString& aName,
ErrorResult& aRv) const
{
return IsInvalidMutableHeader(aName, EmptyCString(), aRv);
}
bool IsInvalidMutableHeader(const nsACString& aName,
const nsACString& aValue,
ErrorResult& aRv) const
{
return IsInvalidName(aName, aRv) ||
IsInvalidValue(aValue, aRv) ||
IsImmutable(aRv) ||
IsForbiddenRequestHeader(aName) ||
IsForbiddenRequestNoCorsHeader(aName, aValue) ||
IsForbiddenResponseHeader(aName);
}
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_InternalHeaders_h

View File

@ -24,7 +24,7 @@ InternalRequest::GetRequestConstructorCopy(nsIGlobalObject* aGlobal, ErrorResult
nsRefPtr<InternalRequest> copy = new InternalRequest();
copy->mURL.Assign(mURL);
copy->SetMethod(mMethod);
copy->mHeaders = new Headers(*mHeaders);
copy->mHeaders = new InternalHeaders(*mHeaders);
copy->mBodyStream = mBodyStream;
copy->mPreserveContentCodings = true;

View File

@ -6,7 +6,8 @@
#ifndef mozilla_dom_InternalRequest_h
#define mozilla_dom_InternalRequest_h
#include "mozilla/dom/Headers.h"
#include "mozilla/dom/HeadersBinding.h"
#include "mozilla/dom/InternalHeaders.h"
#include "mozilla/dom/RequestBinding.h"
#include "mozilla/dom/UnionTypes.h"
@ -55,7 +56,7 @@ public:
explicit InternalRequest()
: mMethod("GET")
, mHeaders(new Headers(nullptr, HeadersGuardEnum::None))
, mHeaders(new InternalHeaders(HeadersGuardEnum::None))
, mContextFrameType(FRAMETYPE_NONE)
, mReferrerType(REFERRER_CLIENT)
, mMode(RequestMode::No_cors)
@ -159,6 +160,12 @@ public:
return mSynchronous;
}
RequestMode
Mode() const
{
return mMode;
}
void
SetMode(RequestMode aMode)
{
@ -177,8 +184,8 @@ public:
return mContext;
}
Headers*
Headers_()
InternalHeaders*
Headers()
{
return mHeaders;
}
@ -225,7 +232,7 @@ private:
nsCString mMethod;
nsCString mURL;
nsRefPtr<Headers> mHeaders;
nsRefPtr<InternalHeaders> mHeaders;
nsCOMPtr<nsIInputStream> mBodyStream;
// nsContentPolicyType does not cover the complete set defined in the spec,

View File

@ -0,0 +1,24 @@
/* -*- Mode: C++; tab-width: 2; 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 "InternalResponse.h"
#include "nsIDOMFile.h"
#include "mozilla/dom/InternalHeaders.h"
namespace mozilla {
namespace dom {
InternalResponse::InternalResponse(uint16_t aStatus, const nsACString& aStatusText)
: mType(ResponseType::Default)
, mStatus(aStatus)
, mStatusText(aStatusText)
, mHeaders(new InternalHeaders(HeadersGuardEnum::Response))
{
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,105 @@
/* -*- Mode: C++; tab-width: 2; 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_InternalResponse_h
#define mozilla_dom_InternalResponse_h
#include "nsIInputStream.h"
#include "nsISupportsImpl.h"
#include "mozilla/dom/ResponseBinding.h"
namespace mozilla {
namespace dom {
class InternalHeaders;
class InternalResponse MOZ_FINAL
{
friend class FetchDriver;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalResponse)
InternalResponse(uint16_t aStatus, const nsACString& aStatusText);
explicit InternalResponse(const InternalResponse& aOther) MOZ_DELETE;
static already_AddRefed<InternalResponse>
NetworkError()
{
nsRefPtr<InternalResponse> response = new InternalResponse(0, EmptyCString());
response->mType = ResponseType::Error;
return response.forget();
}
ResponseType
Type() const
{
return mType;
}
bool
IsError() const
{
return Type() == ResponseType::Error;
}
// FIXME(nsm): Return with exclude fragment.
nsCString&
GetUrl()
{
return mURL;
}
uint16_t
GetStatus() const
{
return mStatus;
}
const nsCString&
GetStatusText() const
{
return mStatusText;
}
InternalHeaders*
Headers()
{
return mHeaders;
}
void
GetBody(nsIInputStream** aStream)
{
nsCOMPtr<nsIInputStream> stream = mBody;
stream.forget(aStream);
}
void
SetBody(nsIInputStream* aBody)
{
mBody = aBody;
}
private:
~InternalResponse()
{ }
ResponseType mType;
nsCString mTerminationReason;
nsCString mURL;
const uint16_t mStatus;
const nsCString mStatusText;
nsRefPtr<InternalHeaders> mHeaders;
nsCOMPtr<nsIInputStream> mBody;
nsCString mContentType;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_InternalResponse_h

View File

@ -5,25 +5,16 @@
#include "Request.h"
#include "nsIUnicodeDecoder.h"
#include "nsIURI.h"
#include "nsDOMString.h"
#include "nsNetUtil.h"
#include "nsPIDOMWindow.h"
#include "nsStreamUtils.h"
#include "nsStringStream.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/EncodingUtils.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/Headers.h"
#include "mozilla/dom/Fetch.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/URL.h"
#include "mozilla/dom/workers/bindings/URL.h"
// dom/workers
#include "WorkerPrivate.h"
namespace mozilla {
@ -31,7 +22,7 @@ namespace dom {
NS_IMPL_CYCLE_COLLECTING_ADDREF(Request)
NS_IMPL_CYCLE_COLLECTING_RELEASE(Request)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Request, mOwner)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Request, mOwner, mHeaders)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Request)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
@ -39,9 +30,9 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Request)
NS_INTERFACE_MAP_END
Request::Request(nsIGlobalObject* aOwner, InternalRequest* aRequest)
: mOwner(aOwner)
: FetchBody<Request>()
, mOwner(aOwner)
, mRequest(aRequest)
, mBodyUsed(false)
{
}
@ -164,24 +155,24 @@ Request::Constructor(const GlobalObject& aGlobal,
request->SetMethod(method);
}
nsRefPtr<Request> domRequest = new Request(global, request);
nsRefPtr<Headers> domRequestHeaders = domRequest->Headers_();
nsRefPtr<InternalHeaders> requestHeaders = request->Headers();
nsRefPtr<Headers> headers;
nsRefPtr<InternalHeaders> headers;
if (aInit.mHeaders.WasPassed()) {
headers = Headers::Constructor(aGlobal, aInit.mHeaders.Value(), aRv);
nsRefPtr<Headers> h = Headers::Constructor(aGlobal, aInit.mHeaders.Value(), aRv);
if (aRv.Failed()) {
return nullptr;
}
headers = h->GetInternalHeaders();
} else {
headers = new Headers(*domRequestHeaders);
headers = new InternalHeaders(*requestHeaders);
}
domRequestHeaders->Clear();
requestHeaders->Clear();
if (domRequest->Mode() == RequestMode::No_cors) {
if (request->Mode() == RequestMode::No_cors) {
nsCString method;
domRequest->GetMethod(method);
request->GetMethod(method);
ToLowerCase(method);
if (!method.EqualsASCII("get") &&
!method.EqualsASCII("head") &&
@ -191,19 +182,19 @@ Request::Constructor(const GlobalObject& aGlobal,
return nullptr;
}
domRequestHeaders->SetGuard(HeadersGuardEnum::Request_no_cors, aRv);
requestHeaders->SetGuard(HeadersGuardEnum::Request_no_cors, aRv);
if (aRv.Failed()) {
return nullptr;
}
}
domRequestHeaders->Fill(*headers, aRv);
requestHeaders->Fill(*headers, aRv);
if (aRv.Failed()) {
return nullptr;
}
if (aInit.mBody.WasPassed()) {
const OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams& bodyInit = aInit.mBody.Value();
const OwningArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams& bodyInit = aInit.mBody.Value();
nsCOMPtr<nsIInputStream> stream;
nsCString contentType;
aRv = ExtractByteStreamFromBody(bodyInit,
@ -214,9 +205,9 @@ Request::Constructor(const GlobalObject& aGlobal,
request->SetBody(stream);
if (!contentType.IsVoid() &&
!domRequestHeaders->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) {
domRequestHeaders->Append(NS_LITERAL_CSTRING("Content-Type"),
contentType, aRv);
!requestHeaders->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) {
requestHeaders->Append(NS_LITERAL_CSTRING("Content-Type"),
contentType, aRv);
}
if (aRv.Failed()) {
@ -224,21 +215,8 @@ Request::Constructor(const GlobalObject& aGlobal,
}
}
// Extract mime type.
nsTArray<nsCString> contentTypeValues;
domRequestHeaders->GetAll(NS_LITERAL_CSTRING("Content-Type"),
contentTypeValues, aRv);
if (aRv.Failed()) {
return nullptr;
}
// HTTP ABNF states Content-Type may have only one value.
// This is from the "parse a header value" of the fetch spec.
if (contentTypeValues.Length() == 1) {
domRequest->mMimeType = contentTypeValues[0];
ToLowerCase(domRequest->mMimeType);
}
nsRefPtr<Request> domRequest = new Request(global, request);
domRequest->SetMimeType(aRv);
return domRequest.forget();
}
@ -252,181 +230,15 @@ Request::Clone() const
return request.forget();
}
namespace {
nsresult
DecodeUTF8(const nsCString& aBuffer, nsString& aDecoded)
Headers*
Request::Headers_()
{
nsCOMPtr<nsIUnicodeDecoder> decoder =
EncodingUtils::DecoderForEncoding("UTF-8");
if (!decoder) {
return NS_ERROR_FAILURE;
if (!mHeaders) {
mHeaders = new Headers(mOwner, mRequest->Headers());
}
int32_t destBufferLen;
nsresult rv =
decoder->GetMaxLength(aBuffer.get(), aBuffer.Length(), &destBufferLen);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!aDecoded.SetCapacity(destBufferLen, fallible_t())) {
return NS_ERROR_OUT_OF_MEMORY;
}
char16_t* destBuffer = aDecoded.BeginWriting();
int32_t srcLen = (int32_t) aBuffer.Length();
int32_t outLen = destBufferLen;
rv = decoder->Convert(aBuffer.get(), &srcLen, destBuffer, &outLen);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(outLen <= destBufferLen);
aDecoded.SetLength(outLen);
return NS_OK;
}
return mHeaders;
}
already_AddRefed<Promise>
Request::ConsumeBody(ConsumeType aType, ErrorResult& aRv)
{
nsRefPtr<Promise> promise = Promise::Create(mOwner, aRv);
if (aRv.Failed()) {
return nullptr;
}
if (BodyUsed()) {
aRv.ThrowTypeError(MSG_REQUEST_BODY_CONSUMED_ERROR);
return nullptr;
}
SetBodyUsed();
// While the spec says to do this asynchronously, all the body constructors
// right now only accept bodies whose streams are backed by an in-memory
// buffer that can be read without blocking. So I think this is fine.
nsCOMPtr<nsIInputStream> stream;
mRequest->GetBody(getter_AddRefs(stream));
if (!stream) {
aRv = NS_NewByteInputStream(getter_AddRefs(stream), "", 0,
NS_ASSIGNMENT_COPY);
if (aRv.Failed()) {
return nullptr;
}
}
AutoJSAPI api;
api.Init(mOwner);
JSContext* cx = api.cx();
// We can make this assertion because for now we only support memory backed
// structures for the body argument for a Request.
MOZ_ASSERT(NS_InputStreamIsBuffered(stream));
nsCString buffer;
uint64_t len;
aRv = stream->Available(&len);
if (aRv.Failed()) {
return nullptr;
}
aRv = NS_ReadInputStreamToString(stream, buffer, len);
if (aRv.Failed()) {
return nullptr;
}
buffer.SetLength(len);
switch (aType) {
case CONSUME_ARRAYBUFFER: {
JS::Rooted<JSObject*> arrayBuffer(cx);
arrayBuffer =
ArrayBuffer::Create(cx, buffer.Length(),
reinterpret_cast<const uint8_t*>(buffer.get()));
JS::Rooted<JS::Value> val(cx);
val.setObjectOrNull(arrayBuffer);
promise->MaybeResolve(cx, val);
return promise.forget();
}
case CONSUME_BLOB: {
// XXXnsm it is actually possible to avoid these duplicate allocations
// for the Blob case by having the Blob adopt the stream's memory
// directly, but I've not added a special case for now.
//
// This is similar to nsContentUtils::CreateBlobBuffer, but also deals
// with worker wrapping.
uint32_t blobLen = buffer.Length();
void* blobData = moz_malloc(blobLen);
nsRefPtr<File> blob;
if (blobData) {
memcpy(blobData, buffer.BeginReading(), blobLen);
blob = File::CreateMemoryFile(GetParentObject(), blobData, blobLen,
NS_ConvertUTF8toUTF16(mMimeType));
} else {
aRv = NS_ERROR_OUT_OF_MEMORY;
return nullptr;
}
promise->MaybeResolve(blob);
return promise.forget();
}
case CONSUME_JSON: {
nsString decoded;
aRv = DecodeUTF8(buffer, decoded);
if (aRv.Failed()) {
return nullptr;
}
JS::Rooted<JS::Value> json(cx);
if (!JS_ParseJSON(cx, decoded.get(), decoded.Length(), &json)) {
JS::Rooted<JS::Value> exn(cx);
if (JS_GetPendingException(cx, &exn)) {
JS_ClearPendingException(cx);
promise->MaybeReject(cx, exn);
}
}
promise->MaybeResolve(cx, json);
return promise.forget();
}
case CONSUME_TEXT: {
nsString decoded;
aRv = DecodeUTF8(buffer, decoded);
if (aRv.Failed()) {
return nullptr;
}
promise->MaybeResolve(decoded);
return promise.forget();
}
}
NS_NOTREACHED("Unexpected consume body type");
// Silence warnings.
return nullptr;
}
already_AddRefed<Promise>
Request::ArrayBuffer(ErrorResult& aRv)
{
return ConsumeBody(CONSUME_ARRAYBUFFER, aRv);
}
already_AddRefed<Promise>
Request::Blob(ErrorResult& aRv)
{
return ConsumeBody(CONSUME_BLOB, aRv);
}
already_AddRefed<Promise>
Request::Json(ErrorResult& aRv)
{
return ConsumeBody(CONSUME_JSON, aRv);
}
already_AddRefed<Promise>
Request::Text(ErrorResult& aRv)
{
return ConsumeBody(CONSUME_TEXT, aRv);
}
} // namespace dom
} // namespace mozilla

View File

@ -9,6 +9,7 @@
#include "nsISupportsImpl.h"
#include "nsWrapperCache.h"
#include "mozilla/dom/Fetch.h"
#include "mozilla/dom/InternalRequest.h"
// Required here due to certain WebIDL enums/classes being declared in both
// files.
@ -21,10 +22,12 @@ namespace mozilla {
namespace dom {
class Headers;
class InternalHeaders;
class Promise;
class Request MOZ_FINAL : public nsISupports
, public nsWrapperCache
, public FetchBody<Request>
{
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Request)
@ -74,13 +77,22 @@ public:
aReferrer.AsAString() = NS_ConvertUTF8toUTF16(mRequest->mReferrerURL);
}
Headers* Headers_() const { return mRequest->Headers_(); }
InternalHeaders*
GetInternalHeaders() const
{
return mRequest->Headers();
}
Headers* Headers_();
void
GetBody(nsIInputStream** aStream) { return mRequest->GetBody(aStream); }
static already_AddRefed<Request>
Constructor(const GlobalObject& aGlobal, const RequestOrScalarValueString& aInput,
const RequestInit& aInit, ErrorResult& rv);
nsISupports* GetParentObject() const
nsIGlobalObject* GetParentObject() const
{
return mOwner;
}
@ -88,51 +100,15 @@ public:
already_AddRefed<Request>
Clone() const;
already_AddRefed<Promise>
ArrayBuffer(ErrorResult& aRv);
already_AddRefed<Promise>
Blob(ErrorResult& aRv);
already_AddRefed<Promise>
Json(ErrorResult& aRv);
already_AddRefed<Promise>
Text(ErrorResult& aRv);
bool
BodyUsed() const
{
return mBodyUsed;
}
already_AddRefed<InternalRequest>
GetInternalRequest();
private:
enum ConsumeType
{
CONSUME_ARRAYBUFFER,
CONSUME_BLOB,
// FormData not supported right now,
CONSUME_JSON,
CONSUME_TEXT,
};
~Request();
already_AddRefed<Promise>
ConsumeBody(ConsumeType aType, ErrorResult& aRv);
void
SetBodyUsed()
{
mBodyUsed = true;
}
nsCOMPtr<nsIGlobalObject> mOwner;
nsRefPtr<InternalRequest> mRequest;
bool mBodyUsed;
nsCString mMimeType;
// Lazily created.
nsRefPtr<Headers> mHeaders;
};
} // namespace dom

View File

@ -4,30 +4,35 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Response.h"
#include "nsDOMString.h"
#include "nsPIDOMWindow.h"
#include "nsIURI.h"
#include "nsISupportsImpl.h"
#include "nsIURI.h"
#include "nsPIDOMWindow.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/Headers.h"
#include "mozilla/dom/Promise.h"
#include "nsDOMString.h"
#include "InternalResponse.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTING_ADDREF(Response)
NS_IMPL_CYCLE_COLLECTING_RELEASE(Response)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Response, mOwner)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Response, mOwner, mHeaders)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Response)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
Response::Response(nsISupports* aOwner)
: mOwner(aOwner)
, mHeaders(new Headers(aOwner))
Response::Response(nsIGlobalObject* aGlobal, InternalResponse* aInternalResponse)
: FetchBody<Response>()
, mOwner(aGlobal)
, mInternalResponse(aInternalResponse)
{
}
@ -38,11 +43,9 @@ Response::~Response()
/* static */ already_AddRefed<Response>
Response::Error(const GlobalObject& aGlobal)
{
ErrorResult result;
ResponseInit init;
init.mStatus = 0;
Optional<ArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams> body;
nsRefPtr<Response> r = Response::Constructor(aGlobal, body, init, result);
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
nsRefPtr<InternalResponse> error = InternalResponse::NetworkError();
nsRefPtr<Response> r = new Response(global, error);
return r.forget();
}
@ -52,87 +55,109 @@ Response::Redirect(const GlobalObject& aGlobal, const nsAString& aUrl,
{
ErrorResult result;
ResponseInit init;
Optional<ArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams> body;
Optional<ArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams> body;
nsRefPtr<Response> r = Response::Constructor(aGlobal, body, init, result);
return r.forget();
}
/*static*/ already_AddRefed<Response>
Response::Constructor(const GlobalObject& global,
const Optional<ArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams>& aBody,
const ResponseInit& aInit, ErrorResult& rv)
Response::Constructor(const GlobalObject& aGlobal,
const Optional<ArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams>& aBody,
const ResponseInit& aInit, ErrorResult& aRv)
{
nsRefPtr<Response> response = new Response(global.GetAsSupports());
return response.forget();
if (aInit.mStatus < 200 || aInit.mStatus > 599) {
aRv.Throw(NS_ERROR_RANGE_ERR);
return nullptr;
}
nsCString statusText;
if (aInit.mStatusText.WasPassed()) {
statusText = aInit.mStatusText.Value();
nsACString::const_iterator start, end;
statusText.BeginReading(start);
statusText.EndReading(end);
if (FindCharInReadable('\r', start, end)) {
aRv.ThrowTypeError(MSG_RESPONSE_INVALID_STATUSTEXT_ERROR);
return nullptr;
}
// Reset iterator since FindCharInReadable advances it.
statusText.BeginReading(start);
if (FindCharInReadable('\n', start, end)) {
aRv.ThrowTypeError(MSG_RESPONSE_INVALID_STATUSTEXT_ERROR);
return nullptr;
}
} else {
// Since we don't support default values for ByteString.
statusText = NS_LITERAL_CSTRING("OK");
}
nsRefPtr<InternalResponse> internalResponse =
new InternalResponse(aInit.mStatus, statusText);
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
nsRefPtr<Response> r = new Response(global, internalResponse);
if (aInit.mHeaders.WasPassed()) {
internalResponse->Headers()->Clear();
// Instead of using Fill, create an object to allow the constructor to
// unwrap the HeadersInit.
nsRefPtr<Headers> headers =
Headers::Constructor(aGlobal, aInit.mHeaders.Value(), aRv);
if (aRv.Failed()) {
return nullptr;
}
internalResponse->Headers()->Fill(*headers->GetInternalHeaders(), aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
}
if (aBody.WasPassed()) {
nsCOMPtr<nsIInputStream> bodyStream;
nsCString contentType;
aRv = ExtractByteStreamFromBody(aBody.Value(), getter_AddRefs(bodyStream), contentType);
internalResponse->SetBody(bodyStream);
if (!contentType.IsVoid() &&
!internalResponse->Headers()->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) {
internalResponse->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), contentType, aRv);
}
if (aRv.Failed()) {
return nullptr;
}
}
r->SetMimeType(aRv);
return r.forget();
}
// FIXME(nsm): Bug 1073231: This is currently unspecced!
already_AddRefed<Response>
Response::Clone()
{
nsRefPtr<Response> response = new Response(mOwner);
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mOwner);
nsRefPtr<Response> response = new Response(global, mInternalResponse);
return response.forget();
}
already_AddRefed<Promise>
Response::ArrayBuffer(ErrorResult& aRv)
void
Response::SetBody(nsIInputStream* aBody)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
MOZ_ASSERT(global);
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
if (aRv.Failed()) {
return nullptr;
}
promise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
return promise.forget();
// FIXME(nsm): Do we flip bodyUsed here?
mInternalResponse->SetBody(aBody);
}
already_AddRefed<Promise>
Response::Blob(ErrorResult& aRv)
Headers*
Response::Headers_()
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
MOZ_ASSERT(global);
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
if (aRv.Failed()) {
return nullptr;
if (!mHeaders) {
mHeaders = new Headers(mOwner, mInternalResponse->Headers());
}
promise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
return promise.forget();
}
already_AddRefed<Promise>
Response::Json(ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
MOZ_ASSERT(global);
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
if (aRv.Failed()) {
return nullptr;
}
promise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
return promise.forget();
}
already_AddRefed<Promise>
Response::Text(ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
MOZ_ASSERT(global);
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
if (aRv.Failed()) {
return nullptr;
}
promise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
return promise.forget();
}
bool
Response::BodyUsed()
{
return false;
return mHeaders;
}
} // namespace dom
} // namespace mozilla

View File

@ -9,25 +9,32 @@
#include "nsWrapperCache.h"
#include "nsISupportsImpl.h"
#include "mozilla/dom/Fetch.h"
#include "mozilla/dom/ResponseBinding.h"
#include "mozilla/dom/UnionTypes.h"
#include "InternalResponse.h"
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
class Headers;
class InternalHeaders;
class Promise;
class Response MOZ_FINAL : public nsISupports
, public nsWrapperCache
, public FetchBody<Response>
{
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Response)
public:
explicit Response(nsISupports* aOwner);
Response(nsIGlobalObject* aGlobal, InternalResponse* aInternalResponse);
Response(const Response& aOther) MOZ_DELETE;
JSObject*
WrapObject(JSContext* aCx)
@ -38,29 +45,37 @@ public:
ResponseType
Type() const
{
return ResponseType::Error;
return mInternalResponse->Type();
}
void
GetUrl(DOMString& aUrl) const
{
aUrl.AsAString() = EmptyString();
aUrl.AsAString() = NS_ConvertUTF8toUTF16(mInternalResponse->GetUrl());
}
uint16_t
Status() const
{
return 400;
return mInternalResponse->GetStatus();
}
void
GetStatusText(nsCString& aStatusText) const
{
aStatusText = EmptyCString();
aStatusText = mInternalResponse->GetStatusText();
}
Headers*
Headers_() const { return mHeaders; }
InternalHeaders*
GetInternalHeaders() const
{
return mInternalResponse->Headers();
}
Headers* Headers_();
void
GetBody(nsIInputStream** aStream) { return mInternalResponse->GetBody(aStream); }
static already_AddRefed<Response>
Error(const GlobalObject& aGlobal);
@ -70,10 +85,10 @@ public:
static already_AddRefed<Response>
Constructor(const GlobalObject& aGlobal,
const Optional<ArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams>& aBody,
const Optional<ArrayBufferOrArrayBufferViewOrBlobOrScalarValueStringOrURLSearchParams>& aBody,
const ResponseInit& aInit, ErrorResult& rv);
nsISupports* GetParentObject() const
nsIGlobalObject* GetParentObject() const
{
return mOwner;
}
@ -81,24 +96,14 @@ public:
already_AddRefed<Response>
Clone();
already_AddRefed<Promise>
ArrayBuffer(ErrorResult& aRv);
already_AddRefed<Promise>
Blob(ErrorResult& aRv);
already_AddRefed<Promise>
Json(ErrorResult& aRv);
already_AddRefed<Promise>
Text(ErrorResult& aRv);
bool
BodyUsed();
void
SetBody(nsIInputStream* aBody);
private:
~Response();
nsCOMPtr<nsISupports> mOwner;
nsCOMPtr<nsIGlobalObject> mOwner;
nsRefPtr<InternalResponse> mInternalResponse;
// Lazily created
nsRefPtr<Headers> mHeaders;
};

View File

@ -7,7 +7,9 @@
EXPORTS.mozilla.dom += [
'Fetch.h',
'Headers.h',
'InternalHeaders.h',
'InternalRequest.h',
'InternalResponse.h',
'Request.h',
'Response.h',
]
@ -15,7 +17,9 @@ EXPORTS.mozilla.dom += [
UNIFIED_SOURCES += [
'Fetch.cpp',
'Headers.cpp',
'InternalHeaders.cpp',
'InternalRequest.cpp',
'InternalResponse.cpp',
'Request.cpp',
'Response.cpp',
]

View File

@ -24,6 +24,7 @@
#include "nsIScriptSecurityManager.h"
#include "nsIXPConnect.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/Event.h"
#include "mozilla/Services.h"
#include "nsContentPermissionHelper.h"
#ifdef MOZ_B2G
@ -360,19 +361,31 @@ NotificationObserver::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData)
{
nsCOMPtr<nsPIDOMWindow> window = mNotification->GetOwner();
if (!window) {
if (!window || !window->IsCurrentInnerWindow()) {
// Window has been closed, this observer is not valid anymore
return NS_ERROR_FAILURE;
}
if (!strcmp("alertclickcallback", aTopic)) {
nsIDocument* doc = window ? window->GetExtantDoc() : nullptr;
if (doc) {
nsContentUtils::DispatchChromeEvent(doc, window,
NS_LITERAL_STRING("DOMWebNotificationClicked"),
true, true);
nsCOMPtr<nsIDOMEvent> event;
NS_NewDOMEvent(getter_AddRefs(event), mNotification, nullptr, nullptr);
nsresult rv = event->InitEvent(NS_LITERAL_STRING("click"), false, true);
NS_ENSURE_SUCCESS(rv, rv);
event->SetTrusted(true);
WantsPopupControlCheck popupControlCheck(event);
bool doDefaultAction = true;
mNotification->DispatchEvent(event, &doDefaultAction);
if (doDefaultAction) {
nsIDocument* doc = window ? window->GetExtantDoc() : nullptr;
if (doc) {
// Browser UI may use DOMWebNotificationClicked to focus the tab
// from which the event was dispatched.
nsContentUtils::DispatchChromeEvent(doc, window->GetOuterWindow(),
NS_LITERAL_STRING("DOMWebNotificationClicked"),
true, true);
}
}
mNotification->DispatchTrustedEvent(NS_LITERAL_STRING("click"));
} else if (!strcmp("alertfinished", aTopic)) {
nsCOMPtr<nsINotificationStorage> notificationStorage =
do_GetService(NS_NOTIFICATION_STORAGE_CONTRACTID);

View File

@ -2857,7 +2857,6 @@ nsresult nsPluginHost::NewPluginURLStream(const nsString& aURL,
principal,
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
nsIContentPolicy::TYPE_OBJECT_SUBREQUEST,
nullptr, // aChannelPolicy
nullptr, // aLoadGroup
listenerPeer);

View File

@ -662,7 +662,6 @@ nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList)
principal,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_OTHER,
nullptr, // aChannelPolicy
loadGroup,
callbacks);

View File

@ -835,6 +835,11 @@ AudioManager::SetStreamVolumeIndex(int32_t aStream, int32_t aIndex) {
static_cast<audio_stream_type_t>(aStream),
aIndex,
AUDIO_DEVICE_OUT_EARPIECE);
status += AudioSystem::setStreamVolumeIndex(
static_cast<audio_stream_type_t>(aStream),
aIndex,
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET);
return status ? NS_ERROR_FAILURE : NS_OK;
#endif
}

View File

@ -8,10 +8,9 @@
*/
typedef object JSON;
// FIXME(nsm): Bug 1071290: Blobs can't be passed as unions in workers.
// FIXME(nsm): Bug 739173: FormData is not available in workers.
// typedef (ArrayBuffer or ArrayBufferView or Blob or FormData or ScalarValueString or URLSearchParams) BodyInit;
typedef (ArrayBuffer or ArrayBufferView or ScalarValueString or URLSearchParams) BodyInit;
typedef (ArrayBuffer or ArrayBufferView or Blob or ScalarValueString or URLSearchParams) BodyInit;
[NoInterfaceObject, Exposed=(Window,Worker)]
interface Body {

View File

@ -87,6 +87,9 @@ dictionary EcdhKeyDeriveParams : Algorithm {
required CryptoKey public;
};
dictionary EcdsaParams : Algorithm {
required AlgorithmIdentifier hash;
};
/***** JWK *****/

View File

@ -6,7 +6,6 @@
#include "ScriptLoader.h"
#include "nsIChannel.h"
#include "nsIChannelPolicy.h"
#include "nsIContentPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIHttpChannel.h"
@ -17,7 +16,6 @@
#include "nsIURI.h"
#include "jsapi.h"
#include "nsChannelPolicy.h"
#include "nsError.h"
#include "nsContentPolicyUtils.h"
#include "nsContentUtils.h"
@ -104,23 +102,6 @@ ChannelFromScriptURL(nsIPrincipal* principal,
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SECURITY_ERR);
}
// Get Content Security Policy from parent document to pass into channel.
nsCOMPtr<nsIContentSecurityPolicy> csp;
rv = principal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIChannelPolicy> channelPolicy;
if (csp) {
channelPolicy = do_CreateInstance(NSCHANNELPOLICY_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = channelPolicy->SetContentSecurityPolicy(csp);
NS_ENSURE_SUCCESS(rv, rv);
rv = channelPolicy->SetLoadType(nsIContentPolicy::TYPE_SCRIPT);
NS_ENSURE_SUCCESS(rv, rv);
}
uint32_t flags = nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI;
nsCOMPtr<nsIChannel> channel;
@ -131,7 +112,6 @@ ChannelFromScriptURL(nsIPrincipal* principal,
parentDoc,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_SCRIPT,
channelPolicy,
loadGroup,
nullptr, // aCallbacks
flags,
@ -148,7 +128,6 @@ ChannelFromScriptURL(nsIPrincipal* principal,
nullPrincipal,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_SCRIPT,
channelPolicy,
loadGroup,
nullptr, // aCallbacks
flags,

View File

@ -2,6 +2,8 @@
support-files =
worker_interfaces.js
worker_test_request.js
worker_test_response.js
[test_interfaces.html]
[test_request.html]
[test_response.html]

View File

@ -0,0 +1,48 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1039846 - Test Response object in worker</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
function runTest() {
var worker = new Worker("worker_test_response.js");
worker.onmessage = function(event) {
if (event.data.type == 'finish') {
SimpleTest.finish();
} else if (event.data.type == 'status') {
ok(event.data.status, event.data.msg);
}
}
worker.onerror = function(event) {
ok(false, "Worker had an error: " + event.message + " at " + event.lineno);
SimpleTest.finish();
};
worker.postMessage(true);
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [
["dom.fetch.enabled", true]
]}, function() {
runTest();
});
</script>
</pre>
</body>
</html>

View File

@ -131,7 +131,6 @@ function testBodyUsed() {
});
}
// FIXME(nsm): Bug 1071290: We can't use Blobs as the body yet.
function testBodyCreation() {
var text = "κόσμε";
var req1 = new Request("", { body: text });
@ -150,6 +149,11 @@ function testBodyCreation() {
is("Hello", v, "Extracted string should match");
});
var reqblob = new Request("", { body: new Blob([text]) });
var pblob = reqblob.text().then(function(v) {
is(v, text, "Extracted string should match");
});
var params = new URLSearchParams();
params.append("item", "Geckos");
params.append("feature", "stickyfeet");
@ -162,7 +166,7 @@ function testBodyCreation() {
is(extracted.get("quantity"), "700", "Param should match");
});
return Promise.all([p1, p2, p2b, p3]);
return Promise.all([p1, p2, p2b, pblob, p3]);
}
function testBodyExtraction() {

View File

@ -0,0 +1,128 @@
function ok(a, msg) {
dump("OK: " + !!a + " => " + a + " " + msg + "\n");
postMessage({type: 'status', status: !!a, msg: a + ": " + msg });
}
function is(a, b, msg) {
dump("IS: " + (a===b) + " => " + a + " | " + b + " " + msg + "\n");
postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg });
}
function testDefaultCtor() {
var res = new Response();
is(res.type, "default", "Default Response type is default");
ok(res.headers instanceof Headers, "Response should have non-null Headers object");
is(res.url, "", "URL should be empty string");
is(res.status, 200, "Default status is 200");
is(res.statusText, "OK", "Default statusText is OK");
}
function testClone() {
var res = (new Response("This is a body", {
status: 404,
statusText: "Not Found",
headers: { "Content-Length": 5 },
})).clone();
is(res.status, 404, "Response status is 404");
is(res.statusText, "Not Found", "Response statusText is POST");
ok(res.headers instanceof Headers, "Response should have non-null Headers object");
is(res.headers.get('content-length'), "5", "Response content-length should be 5.");
}
function testBodyUsed() {
var res = new Response("Sample body");
ok(!res.bodyUsed, "bodyUsed is initially false.");
return res.text().then((v) => {
is(v, "Sample body", "Body should match");
ok(res.bodyUsed, "After reading body, bodyUsed should be true.");
}).then(() => {
return res.blob().then((v) => {
ok(false, "Attempting to read body again should fail.");
}, (e) => {
ok(true, "Attempting to read body again should fail.");
})
});
}
function testBodyCreation() {
var text = "κόσμε";
var res1 = new Response(text);
var p1 = res1.text().then(function(v) {
ok(typeof v === "string", "Should resolve to string");
is(text, v, "Extracted string should match");
});
var res2 = new Response(new Uint8Array([72, 101, 108, 108, 111]));
var p2 = res2.text().then(function(v) {
is("Hello", v, "Extracted string should match");
});
var res2b = new Response((new Uint8Array([72, 101, 108, 108, 111])).buffer);
var p2b = res2b.text().then(function(v) {
is("Hello", v, "Extracted string should match");
});
var resblob = new Response(new Blob([text]));
var pblob = resblob.text().then(function(v) {
is(v, text, "Extracted string should match");
});
var params = new URLSearchParams();
params.append("item", "Geckos");
params.append("feature", "stickyfeet");
params.append("quantity", "700");
var res3 = new Response(params);
var p3 = res3.text().then(function(v) {
var extracted = new URLSearchParams(v);
is(extracted.get("item"), "Geckos", "Param should match");
is(extracted.get("feature"), "stickyfeet", "Param should match");
is(extracted.get("quantity"), "700", "Param should match");
});
return Promise.all([p1, p2, p2b, pblob, p3]);
}
function testBodyExtraction() {
var text = "κόσμε";
var newRes = function() { return new Response(text); }
return newRes().text().then(function(v) {
ok(typeof v === "string", "Should resolve to string");
is(text, v, "Extracted string should match");
}).then(function() {
return newRes().blob().then(function(v) {
ok(v instanceof Blob, "Should resolve to Blob");
var fs = new FileReaderSync();
is(fs.readAsText(v), text, "Decoded Blob should match original");
});
}).then(function() {
return newRes().json().then(function(v) {
ok(false, "Invalid json should reject");
}, function(e) {
ok(true, "Invalid json should reject");
})
}).then(function() {
return newRes().arrayBuffer().then(function(v) {
ok(v instanceof ArrayBuffer, "Should resolve to ArrayBuffer");
var dec = new TextDecoder();
is(dec.decode(new Uint8Array(v)), text, "UTF-8 decoded ArrayBuffer should match original");
});
})
}
onmessage = function() {
var done = function() { postMessage({ type: 'finish' }) }
testDefaultCtor();
testClone();
Promise.resolve()
.then(testBodyCreation)
.then(testBodyUsed)
.then(testBodyExtraction)
// Put more promise based tests here.
.then(done)
.catch(function(e) {
ok(false, "Some Response tests failed " + e);
done();
})
}

View File

@ -1076,7 +1076,6 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoun
requestingPrincipal,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_OTHER,
nullptr, // aChannelPolicy
loadGroup);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -449,7 +449,6 @@ XMLDocument::Load(const nsAString& aUrl, ErrorResult& aRv)
static_cast<nsIDocument*>(this),
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_XMLHTTPREQUEST,
nullptr, // aChannelPolicy
loadGroup,
req,
nsIRequest::LOAD_BACKGROUND);

View File

@ -64,7 +64,6 @@ URIUtils::ResetWithSource(nsIDocument *aNewDoc, nsIDOMNode *aSourceNode)
sourceDoc,
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
nsIContentPolicy::TYPE_OTHER,
nullptr, // aChannelPolicy
loadGroup);
if (NS_FAILED(rv)) {

View File

@ -465,7 +465,6 @@ txCompileObserver::startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler,
aReferrerPrincipal,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_STYLESHEET,
nullptr,
loadGroup);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -23,7 +23,6 @@
#include "nsUnicharUtils.h"
#include "nsIDocument.h"
#include "nsIPrincipal.h"
#include "nsIChannelPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIContentPolicy.h"
#include "nsAutoPtr.h"
@ -268,22 +267,9 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgRe
nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue;
nsAutoString bgStringValue;
// get Content Security Policy to pass to LoadImage
nsCOMPtr<nsIDocument> doc(do_QueryInterface(document));
nsCOMPtr<nsIPrincipal> principal;
nsCOMPtr<nsIChannelPolicy> channelPolicy;
nsCOMPtr<nsIContentSecurityPolicy> csp;
if (doc) {
principal = doc->NodePrincipal();
nsresult rv = principal->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, rv);
if (csp) {
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
channelPolicy->SetContentSecurityPolicy(csp);
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE);
}
}
nsCOMPtr<nsIPrincipal> principal = doc ? doc->NodePrincipal() : nullptr;
while (true) {
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(domNode));
// bail for the parent node of the root element or null argument
@ -310,7 +296,7 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgRe
return il->LoadImage(bgUri, nullptr, nullptr, principal, nullptr,
nullptr, nullptr, nsIRequest::LOAD_NORMAL,
nullptr, channelPolicy, EmptyString(), aRequest);
nullptr, EmptyString(), aRequest);
}
}

View File

@ -1205,7 +1205,6 @@ nsresult nsWebBrowserPersist::SaveURIInternal(
nsContentUtils::GetSystemPrincipal(),
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_OTHER,
nullptr, // aChannelPolicy
nullptr, // aLoadGroup
static_cast<nsIInterfaceRequestor*>(this),
loadFlags);

View File

@ -281,7 +281,6 @@ nsresult nsAutoConfig::downloadAutoConfig()
nsContentUtils::GetSystemPrincipal(),
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_OTHER,
nullptr, // aChannelPolicy
nullptr, // loadGroup
nullptr, // aCallbacks
nsIRequest::INHIBIT_PERSISTENT_CACHING |

Some files were not shown because too many files have changed in this diff Show More