merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-10-11 12:01:35 +02:00
commit cd1be634c9
73 changed files with 723 additions and 512 deletions

View File

@ -11,7 +11,7 @@ var gDragDataHelper = {
getLinkFromDragEvent: function DragDataHelper_getLinkFromDragEvent(aEvent) {
let dt = aEvent.dataTransfer;
if (!dt || !dt.types.contains(this.mimeType)) {
if (!dt || !dt.types.includes(this.mimeType)) {
return null;
}

View File

@ -44,7 +44,7 @@ add_task(function*() {
let dt = event.clipboardData;
is(dt.types.length, 3, "number of types");
ok(dt.types.contains("text/plain"), "text/plain exists in types");
ok(dt.types.includes("text/plain"), "text/plain exists in types");
ok(dt.mozTypesAt(0).contains("text/plain"), "text/plain exists in mozTypesAt");
is(dt.getData("text/plain"), "Alternate", "text/plain returned in getData");
is(dt.mozGetDataAt("text/plain", 0), "Alternate", "text/plain returned in mozGetDataAt");

View File

@ -656,10 +656,10 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
<parameter name="aEvent"/>
<body>
var types = aEvent.dataTransfer.types;
if (types.contains("application/x-moz-file") ||
types.contains("text/x-moz-url") ||
types.contains("text/uri-list") ||
types.contains("text/unicode"))
if (types.includes("application/x-moz-file") ||
types.includes("text/x-moz-url") ||
types.includes("text/uri-list") ||
types.includes("text/unicode"))
aEvent.preventDefault();
</body>
</method>

View File

@ -1391,9 +1391,9 @@ DownloadsPlacesView.prototype = {
onDragOver(aEvent) {
let types = aEvent.dataTransfer.types;
if (types.contains("text/uri-list") ||
types.contains("text/x-moz-url") ||
types.contains("text/plain")) {
if (types.includes("text/uri-list") ||
types.includes("text/x-moz-url") ||
types.includes("text/plain")) {
aEvent.preventDefault();
}
},

View File

@ -12,11 +12,6 @@
window.parent.postMessage("OK", "http://mochi.test:8888");
};
setTimeout(function() {
window.parent.postMessage("KO", "http://mochi.test:8888");
}, 1000);
</script>
</head>
<body>

View File

@ -856,7 +856,7 @@
<handler event="dragover">
<![CDATA[
var types = event.dataTransfer.types;
if (types.contains("text/plain") || types.contains("text/x-moz-text-internal"))
if (types.includes("text/plain") || types.includes("text/x-moz-text-internal"))
event.preventDefault();
]]>
</handler>

View File

@ -44,8 +44,7 @@ public:
NS_DECL_NSIDOMLOCATION
#define THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME() { \
MOZ_ASSERT(aSubjectPrincipal.isSome()); \
if (!CallerSubsumes(aSubjectPrincipal.value())) { \
if (!CallerSubsumes(&aSubjectPrincipal)) { \
aError.Throw(NS_ERROR_DOM_SECURITY_ERR); \
return; \
} \
@ -53,7 +52,7 @@ public:
// WebIDL API:
void Assign(const nsAString& aUrl,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -61,14 +60,14 @@ public:
}
void Replace(const nsAString& aUrl,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
aError = Replace(aUrl);
}
void Reload(bool aForceget,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -76,7 +75,7 @@ public:
}
void GetHref(nsAString& aHref,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -84,14 +83,14 @@ public:
}
void SetHref(const nsAString& aHref,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
aError = SetHref(aHref);
}
void GetOrigin(nsAString& aOrigin,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -99,7 +98,7 @@ public:
}
void GetProtocol(nsAString& aProtocol,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -107,7 +106,7 @@ public:
}
void SetProtocol(const nsAString& aProtocol,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -115,7 +114,7 @@ public:
}
void GetHost(nsAString& aHost,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -123,7 +122,7 @@ public:
}
void SetHost(const nsAString& aHost,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -131,7 +130,7 @@ public:
}
void GetHostname(nsAString& aHostname,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -139,7 +138,7 @@ public:
}
void SetHostname(const nsAString& aHostname,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -147,7 +146,7 @@ public:
}
void GetPort(nsAString& aPort,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -155,7 +154,7 @@ public:
}
void SetPort(const nsAString& aPort,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -163,7 +162,7 @@ public:
}
void GetPathname(nsAString& aPathname,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -171,7 +170,7 @@ public:
}
void SetPathname(const nsAString& aPathname,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -179,7 +178,7 @@ public:
}
void GetSearch(nsAString& aSeach,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -187,7 +186,7 @@ public:
}
void SetSearch(const nsAString& aSeach,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -195,7 +194,7 @@ public:
}
void GetHash(nsAString& aHash,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -203,7 +202,7 @@ public:
}
void SetHash(const nsAString& aHash,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
@ -211,7 +210,7 @@ public:
}
void Stringify(nsAString& aRetval,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
// GetHref checks CallerSubsumes.

View File

@ -138,11 +138,11 @@ ContentAreaDropListener.prototype =
let dataTransfer = aEvent.dataTransfer;
let types = dataTransfer.types;
if (!types.contains("application/x-moz-file") &&
!types.contains("text/x-moz-url") &&
!types.contains("text/uri-list") &&
!types.contains("text/x-moz-text-internal") &&
!types.contains("text/plain"))
if (!types.includes("application/x-moz-file") &&
!types.includes("text/x-moz-url") &&
!types.includes("text/uri-list") &&
!types.includes("text/x-moz-text-internal") &&
!types.includes("text/plain"))
return false;
if (aAllowSameDocument)

View File

@ -6241,6 +6241,14 @@ nsDocument::LoadBindingDocument(const nsAString& aURI)
return rv.StealNSResult();
}
void
nsIDocument::LoadBindingDocument(const nsAString& aURI,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& rv)
{
LoadBindingDocument(aURI, Some(&aSubjectPrincipal), rv);
}
void
nsIDocument::LoadBindingDocument(const nsAString& aURI,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,

View File

@ -6817,13 +6817,12 @@ nsGlobalWindow::CanMoveResizeWindows(bool aCallerIsChrome)
bool
nsGlobalWindow::AlertOrConfirm(bool aAlert,
const nsAString& aMessage,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
// XXX This method is very similar to nsGlobalWindow::Prompt, make
// sure any modifications here don't need to happen over there!
MOZ_ASSERT(IsOuterWindow());
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (!AreDialogsEnabled()) {
// Just silently return. In the case of alert(), the return value is
@ -6842,7 +6841,7 @@ nsGlobalWindow::AlertOrConfirm(bool aAlert,
EnsureReflowFlushAndPaint();
nsAutoString title;
MakeScriptDialogTitle(title, aSubjectPrincipal.value());
MakeScriptDialogTitle(title, &aSubjectPrincipal);
// Remove non-terminating null characters from the
// string. See bug #310037.
@ -6895,7 +6894,7 @@ nsGlobalWindow::AlertOrConfirm(bool aAlert,
}
void
nsGlobalWindow::Alert(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsGlobalWindow::Alert(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
MOZ_ASSERT(IsInnerWindow());
@ -6904,7 +6903,7 @@ nsGlobalWindow::Alert(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
void
nsGlobalWindow::AlertOuter(const nsAString& aMessage,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
@ -6913,7 +6912,7 @@ nsGlobalWindow::AlertOuter(const nsAString& aMessage,
void
nsGlobalWindow::Alert(const nsAString& aMessage,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(AlertOuter, (aMessage, aSubjectPrincipal, aError),
@ -6922,7 +6921,7 @@ nsGlobalWindow::Alert(const nsAString& aMessage,
bool
nsGlobalWindow::ConfirmOuter(const nsAString& aMessage,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
@ -6933,7 +6932,7 @@ nsGlobalWindow::ConfirmOuter(const nsAString& aMessage,
bool
nsGlobalWindow::Confirm(const nsAString& aMessage,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(ConfirmOuter, (aMessage, aSubjectPrincipal, aError),
@ -6951,13 +6950,12 @@ void
nsGlobalWindow::PromptOuter(const nsAString& aMessage,
const nsAString& aInitial,
nsAString& aReturn,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
// XXX This method is very similar to nsGlobalWindow::AlertOrConfirm, make
// sure any modifications here don't need to happen over there!
MOZ_RELEASE_ASSERT(IsOuterWindow());
MOZ_ASSERT(aSubjectPrincipal.isSome());
SetDOMStringToNull(aReturn);
@ -6976,7 +6974,7 @@ nsGlobalWindow::PromptOuter(const nsAString& aMessage,
EnsureReflowFlushAndPaint();
nsAutoString title;
MakeScriptDialogTitle(title, aSubjectPrincipal.value());
MakeScriptDialogTitle(title, &aSubjectPrincipal);
// Remove non-terminating null characters from the
// string. See bug #310037.
@ -7037,7 +7035,7 @@ nsGlobalWindow::PromptOuter(const nsAString& aMessage,
void
nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial,
nsAString& aReturn,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(PromptOuter,
@ -8283,11 +8281,10 @@ void
nsGlobalWindow::PostMessageMozOuter(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const nsAString& aTargetOrigin,
JS::Handle<JS::Value> aTransfer,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
MOZ_ASSERT(aSubjectPrincipal.isSome());
//
// Window.postMessage is an intentional subversion of the same-origin policy.
@ -8370,7 +8367,7 @@ nsGlobalWindow::PostMessageMozOuter(JSContext* aCx, JS::Handle<JS::Value> aMessa
}
PrincipalOriginAttributes attrs =
BasePrincipal::Cast(aSubjectPrincipal.value())->OriginAttributesRef();
BasePrincipal::Cast(&aSubjectPrincipal)->OriginAttributesRef();
// Create a nsIPrincipal inheriting the app/browser attributes from the
// caller.
providedPrincipal = BasePrincipal::CreateCodebasePrincipal(originURI, attrs);
@ -8408,7 +8405,7 @@ void
nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const nsAString& aTargetOrigin,
JS::Handle<JS::Value> aTransfer,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(PostMessageMozOuter,
@ -8421,7 +8418,7 @@ void
nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const nsAString& aTargetOrigin,
const Optional<Sequence<JS::Value>>& aTransfer,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
@ -9049,10 +9046,9 @@ nsGlobalWindow::CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
}
Element*
nsGlobalWindow::GetFrameElementOuter(const Maybe<nsIPrincipal*>& aSubjectPrincipal)
nsGlobalWindow::GetFrameElementOuter(nsIPrincipal& aSubjectPrincipal)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (!mDocShell || mDocShell->GetIsMozBrowserOrApp()) {
return nullptr;
@ -9064,8 +9060,7 @@ nsGlobalWindow::GetFrameElementOuter(const Maybe<nsIPrincipal*>& aSubjectPrincip
return nullptr;
}
if (!aSubjectPrincipal.value()->
SubsumesConsideringDomain(element->NodePrincipal())) {
if (!aSubjectPrincipal.SubsumesConsideringDomain(element->NodePrincipal())) {
return nullptr;
}
@ -9073,7 +9068,7 @@ nsGlobalWindow::GetFrameElementOuter(const Maybe<nsIPrincipal*>& aSubjectPrincip
}
Element*
nsGlobalWindow::GetFrameElement(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsGlobalWindow::GetFrameElement(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(GetFrameElementOuter, (aSubjectPrincipal), aError,
@ -9252,11 +9247,10 @@ already_AddRefed<nsIVariant>
nsGlobalWindow::ShowModalDialogOuter(const nsAString& aUrl,
nsIVariant* aArgument,
const nsAString& aOptions,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (mDoc) {
mDoc->WarnOnceAbout(nsIDocument::eShowModalDialog);
@ -9268,7 +9262,7 @@ nsGlobalWindow::ShowModalDialogOuter(const nsAString& aUrl,
}
RefPtr<DialogValueHolder> argHolder =
new DialogValueHolder(aSubjectPrincipal.value(), aArgument);
new DialogValueHolder(&aSubjectPrincipal, aArgument);
// Before bringing up the window/dialog, unsuppress painting and flush
// pending reflows.
@ -9325,7 +9319,7 @@ nsGlobalWindow::ShowModalDialogOuter(const nsAString& aUrl,
already_AddRefed<nsIVariant>
nsGlobalWindow::ShowModalDialog(const nsAString& aUrl, nsIVariant* aArgument,
const nsAString& aOptions,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(ShowModalDialogOuter,
@ -9338,7 +9332,7 @@ nsGlobalWindow::ShowModalDialog(JSContext* aCx, const nsAString& aUrl,
JS::Handle<JS::Value> aArgument,
const nsAString& aOptions,
JS::MutableHandle<JS::Value> aRetval,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
MOZ_ASSERT(IsInnerWindow());
@ -10587,8 +10581,7 @@ nsGlobalWindow::GetSessionStorage(ErrorResult& aError)
}
DOMStorage*
nsGlobalWindow::GetLocalStorage(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& aError)
nsGlobalWindow::GetLocalStorage(ErrorResult& aError)
{
MOZ_RELEASE_ASSERT(IsInnerWindow());
@ -10597,7 +10590,8 @@ nsGlobalWindow::GetLocalStorage(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
}
if (!mLocalStorage) {
if (!DOMStorage::CanUseStorage(AsInner(), aSubjectPrincipal)) {
if (nsContentUtils::StorageAllowedForWindow(AsInner()) ==
nsContentUtils::StorageAccess::eDeny) {
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr;
}
@ -11663,10 +11657,7 @@ nsGlobalWindow::CloneStorageEvent(const nsAString& aType,
RefPtr<DOMStorage> storage;
if (storageArea->GetType() == DOMStorage::LocalStorage) {
storage = GetLocalStorage(nsContentUtils::GetCurrentJSContext()
? Some(nsContentUtils::SubjectPrincipal())
: Nothing(),
aRv);
storage = GetLocalStorage(aRv);
} else {
MOZ_ASSERT(storageArea->GetType() == DOMStorage::SessionStorage);
storage = GetSessionStorage(aRv);
@ -14001,11 +13992,10 @@ NS_IMPL_RELEASE_INHERITED(nsGlobalModalWindow, nsGlobalWindow)
void
nsGlobalWindow::GetDialogArgumentsOuter(JSContext* aCx,
JS::MutableHandle<JS::Value> aRetval,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
MOZ_ASSERT(aSubjectPrincipal.isSome());
MOZ_ASSERT(IsModalContentWindow(),
"This should only be called on modal windows!");
@ -14019,14 +14009,13 @@ nsGlobalWindow::GetDialogArgumentsOuter(JSContext* aCx,
// does not subsumes the origin of the arguments.
JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
JSAutoCompartment ac(aCx, wrapper);
mDialogArguments->Get(aCx, wrapper, aSubjectPrincipal.value(),
aRetval, aError);
mDialogArguments->Get(aCx, wrapper, &aSubjectPrincipal, aRetval, aError);
}
void
nsGlobalWindow::GetDialogArguments(JSContext* aCx,
JS::MutableHandle<JS::Value> aRetval,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(GetDialogArgumentsOuter,
@ -14070,19 +14059,17 @@ nsGlobalWindow::InitWasOffline()
void
nsGlobalWindow::GetReturnValueOuter(JSContext* aCx,
JS::MutableHandle<JS::Value> aReturnValue,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
MOZ_ASSERT(aSubjectPrincipal.isSome());
MOZ_ASSERT(IsModalContentWindow(),
"This should only be called on modal windows!");
if (mReturnValue) {
JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
JSAutoCompartment ac(aCx, wrapper);
mReturnValue->Get(aCx, wrapper, aSubjectPrincipal.value(),
aReturnValue, aError);
mReturnValue->Get(aCx, wrapper, &aSubjectPrincipal, aReturnValue, aError);
} else {
aReturnValue.setUndefined();
}
@ -14091,7 +14078,7 @@ nsGlobalWindow::GetReturnValueOuter(JSContext* aCx,
void
nsGlobalWindow::GetReturnValue(JSContext* aCx,
JS::MutableHandle<JS::Value> aReturnValue,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(GetReturnValueOuter,
@ -14115,11 +14102,10 @@ nsGlobalModalWindow::GetReturnValue(nsIVariant **aRetVal)
void
nsGlobalWindow::SetReturnValueOuter(JSContext* aCx,
JS::Handle<JS::Value> aReturnValue,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
MOZ_ASSERT(aSubjectPrincipal.isSome());
MOZ_ASSERT(IsModalContentWindow(),
"This should only be called on modal windows!");
@ -14128,15 +14114,14 @@ nsGlobalWindow::SetReturnValueOuter(JSContext* aCx,
nsContentUtils::XPConnect()->JSToVariant(aCx, aReturnValue,
getter_AddRefs(returnValue));
if (!aError.Failed()) {
mReturnValue = new DialogValueHolder(aSubjectPrincipal.value(),
returnValue);
mReturnValue = new DialogValueHolder(&aSubjectPrincipal, returnValue);
}
}
void
nsGlobalWindow::SetReturnValue(JSContext* aCx,
JS::Handle<JS::Value> aReturnValue,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(SetReturnValueOuter,

View File

@ -937,9 +937,9 @@ public:
nsPIDOMWindowOuter* GetScriptableParent() override;
nsPIDOMWindowOuter* GetScriptableParentOrNull() override;
mozilla::dom::Element*
GetFrameElementOuter(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal);
GetFrameElementOuter(nsIPrincipal& aSubjectPrincipal);
mozilla::dom::Element*
GetFrameElement(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
GetFrameElement(nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
already_AddRefed<nsIDOMElement> GetFrameElement() override;
already_AddRefed<nsPIDOMWindowOuter>
@ -982,31 +982,31 @@ public:
protected:
bool AlertOrConfirm(bool aAlert, const nsAString& aMessage,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
public:
void Alert(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
void Alert(nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
void AlertOuter(const nsAString& aMessage,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
void Alert(const nsAString& aMessage,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
bool ConfirmOuter(const nsAString& aMessage,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
bool Confirm(const nsAString& aMessage,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
void PromptOuter(const nsAString& aMessage, const nsAString& aInitial,
nsAString& aReturn,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
void Prompt(const nsAString& aMessage, const nsAString& aInitial,
nsAString& aReturn,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
already_AddRefed<mozilla::dom::cache::CacheStorage> GetCaches(mozilla::ErrorResult& aRv);
already_AddRefed<mozilla::dom::Promise> Fetch(const mozilla::dom::RequestOrUSVString& aInput,
@ -1018,12 +1018,12 @@ public:
JS::Handle<JS::Value> aArgument,
const nsAString& aOptions,
JS::MutableHandle<JS::Value> aRetval,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const nsAString& aTargetOrigin,
const mozilla::dom::Optional<mozilla::dom::Sequence<JS::Value > >& aTransfer,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
int32_t SetTimeout(JSContext* aCx, mozilla::dom::Function& aFunction,
int32_t aTimeout,
@ -1049,8 +1049,7 @@ public:
mozilla::ErrorResult& aError);
mozilla::dom::DOMStorage* GetSessionStorage(mozilla::ErrorResult& aError);
mozilla::dom::DOMStorage*
GetLocalStorage(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
mozilla::ErrorResult& aError);
GetLocalStorage(mozilla::ErrorResult& aError);
mozilla::dom::Selection* GetSelectionOuter();
mozilla::dom::Selection* GetSelection(mozilla::ErrorResult& aError);
already_AddRefed<nsISelection> GetSelection() override;
@ -1270,22 +1269,22 @@ public:
mozilla::ErrorResult& aError);
void GetDialogArgumentsOuter(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
void GetDialogArguments(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
void GetReturnValueOuter(JSContext* aCx, JS::MutableHandle<JS::Value> aReturnValue,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
void GetReturnValue(JSContext* aCx, JS::MutableHandle<JS::Value> aReturnValue,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
void SetReturnValueOuter(JSContext* aCx, JS::Handle<JS::Value> aReturnValue,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
void SetReturnValue(JSContext* aCx, JS::Handle<JS::Value> aReturnValue,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
void GetInterface(JSContext* aCx, nsIJSID* aIID,
@ -1708,24 +1707,24 @@ protected:
void PostMessageMozOuter(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const nsAString& aTargetOrigin,
JS::Handle<JS::Value> aTransfer,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const nsAString& aTargetOrigin,
JS::Handle<JS::Value> aTransfer,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
already_AddRefed<nsIVariant>
ShowModalDialogOuter(const nsAString& aUrl, nsIVariant* aArgument,
const nsAString& aOptions,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
already_AddRefed<nsIVariant>
ShowModalDialog(const nsAString& aUrl, nsIVariant* aArgument,
const nsAString& aOptions,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aError);
// Ask the user if further dialogs should be blocked, if dialogs are currently

View File

@ -2687,6 +2687,9 @@ public:
const nsAString& aAttrName,
const nsAString& aAttrValue);
Element* GetBindingParent(nsINode& aNode);
void LoadBindingDocument(const nsAString& aURI,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& rv);
void LoadBindingDocument(const nsAString& aURI,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
mozilla::ErrorResult& rv);

View File

@ -3537,10 +3537,8 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason, bool aIgnoreCurrentTyp
}
nsIDocument*
nsObjectLoadingContent::GetContentDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
nsObjectLoadingContent::GetContentDocument(nsIPrincipal& aSubjectPrincipal)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
@ -3554,7 +3552,7 @@ nsObjectLoadingContent::GetContentDocument(const mozilla::Maybe<nsIPrincipal*>&
}
// Return null for cross-origin contentDocument.
if (!aSubjectPrincipal.value()->SubsumesConsideringDomain(sub_doc->NodePrincipal())) {
if (!aSubjectPrincipal.SubsumesConsideringDomain(sub_doc->NodePrincipal())) {
return nullptr;
}

View File

@ -180,7 +180,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent
mozilla::ErrorResult& aRv);
// WebIDL API
nsIDocument* GetContentDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal);
nsIDocument* GetContentDocument(nsIPrincipal& aSubjectPrincipal);
void GetActualType(nsAString& aType) const
{
CopyUTF8toUTF16(mContentType, aType);

View File

@ -6907,13 +6907,13 @@ class CGCallGenerator(CGThing):
value, resultVar can be omitted.
"""
def __init__(self, isFallible, needsSubjectPrincipal, arguments, argsPre,
returnType, extendedAttributes, descriptorProvider,
returnType, extendedAttributes, descriptor,
nativeMethodName, static, object="self", argsPost=[],
resultVar=None):
CGThing.__init__(self)
result, resultOutParam, resultRooter, resultArgs, resultConversion = \
getRetvalDeclarationForType(returnType, descriptorProvider)
getRetvalDeclarationForType(returnType, descriptor)
args = CGList([CGGeneric(arg) for arg in argsPre], ", ")
for a, name in arguments:
@ -7008,16 +7008,32 @@ class CGCallGenerator(CGThing):
self.cgRoot.append(call)
if needsSubjectPrincipal:
self.cgRoot.prepend(CGGeneric(dedent(
"""
Maybe<nsIPrincipal*> subjectPrincipal;
if (NS_IsMainThread()) {
JSCompartment* compartment = js::GetContextCompartment(cx);
MOZ_ASSERT(compartment);
JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
subjectPrincipal.emplace(nsJSPrincipals::get(principals));
}
""")))
getPrincipal = dedent(
"""
JSCompartment* compartment = js::GetContextCompartment(cx);
MOZ_ASSERT(compartment);
JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
""")
if descriptor.interface.isExposedInAnyWorker():
self.cgRoot.prepend(CGGeneric(fill(
"""
Maybe<nsIPrincipal*> subjectPrincipal;
if (NS_IsMainThread()) {
$*{getPrincipal}
subjectPrincipal.emplace(nsJSPrincipals::get(principals));
}
""",
getPrincipal=getPrincipal)))
else:
self.cgRoot.prepend(CGGeneric(fill(
"""
$*{getPrincipal}
// Initializing a nonnull is pretty darn annoying...
NonNull<nsIPrincipal> subjectPrincipal;
subjectPrincipal = static_cast<nsIPrincipal*>(nsJSPrincipals::get(principals));
""",
getPrincipal=getPrincipal)))
if isFallible:
self.cgRoot.prepend(CGGeneric("binding_detail::FastErrorResult rv;\n"))
@ -13993,7 +14009,7 @@ class CGNativeMember(ClassMethod):
# And the nsIPrincipal
if self.member.getExtendedAttribute('NeedsSubjectPrincipal'):
args.append(Argument("const Maybe<nsIPrincipal*>&", "aPrincipal"))
args.append(Argument("nsIPrincipal&", "aPrincipal"))
# And the ErrorResult
if 'infallible' not in self.extendedAttrs:
# Use aRv so it won't conflict with local vars named "rv"

View File

@ -933,6 +933,9 @@ public:
void SetThrowingGetterAttr(bool arg);
bool ThrowingSetterAttr() const;
void SetThrowingSetterAttr(bool arg, ErrorResult& aRv);
void NeedsSubjectPrincipalMethod(nsIPrincipal&);
bool NeedsSubjectPrincipalAttr(nsIPrincipal&);
void SetNeedsSubjectPrincipalAttr(bool, nsIPrincipal&);
int16_t LegacyCall(const JS::Value&, uint32_t, TestInterface&);
void PassArgsWithDefaults(JSContext*, const Optional<int32_t>&,
TestInterface*, const Dict&, double,

View File

@ -943,6 +943,8 @@ interface TestInterface {
[Throws] attribute boolean throwingAttr;
[GetterThrows] attribute boolean throwingGetterAttr;
[SetterThrows] attribute boolean throwingSetterAttr;
[NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
[NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
legacycaller short(unsigned long arg1, TestInterface arg2);
void passArgsWithDefaults(optional long arg1,
optional TestInterface? arg2 = null,

View File

@ -794,6 +794,10 @@ interface TestJSImplInterface {
[Throws] attribute boolean throwingAttr;
[GetterThrows] attribute boolean throwingGetterAttr;
[SetterThrows] attribute boolean throwingSetterAttr;
// NeedsSubjectPrincipal not supported on JS-implemented things for
// now, because we always pass in the caller principal anyway.
// [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
// [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
// legacycaller short(unsigned long arg1, TestInterface arg2);
void passArgsWithDefaults(optional long arg1,
optional TestInterface? arg2 = null,

View File

@ -76,7 +76,7 @@ ClipboardEvent::Constructor(const GlobalObject& aGlobal,
// checked properly within DataTransfer.
clipboardData = new DataTransfer(ToSupports(e), eCopy, false, -1);
clipboardData->SetData(aParam.mDataType, aParam.mData,
Some(aGlobal.GetSubjectPrincipal()), aRv);
*aGlobal.GetSubjectPrincipal(), aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
}
}

View File

@ -284,11 +284,10 @@ DataTransfer::GetMozUserCancelled(bool* aUserCancelled)
}
already_AddRefed<FileList>
DataTransfer::GetFiles(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
DataTransfer::GetFiles(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
return mItems->Files(aSubjectPrincipal.value());
return mItems->Files(&aSubjectPrincipal);
}
NS_IMETHODIMP
@ -310,21 +309,24 @@ DataTransfer::GetFiles(nsIDOMFileList** aFileList)
return NS_OK;
}
already_AddRefed<DOMStringList>
DataTransfer::GetTypes(ErrorResult& aRv) const
void
DataTransfer::GetTypes(nsTArray<nsString>& aTypes,
nsIPrincipal& aSubjectPrincipal) const
{
RefPtr<DOMStringList> types = new DOMStringList();
// When called from bindings, aTypes will be empty, but since we might have
// Gecko-internal callers too, clear it to be safe.
aTypes.Clear();
const nsTArray<RefPtr<DataTransferItem>>* items = mItems->MozItemsAt(0);
if (NS_WARN_IF(!items)) {
return types.forget();
return;
}
for (uint32_t i = 0; i < items->Length(); i++) {
DataTransferItem* item = items->ElementAt(i);
MOZ_ASSERT(item);
if (item->ChromeOnly() && !nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
if (item->ChromeOnly() && !nsContentUtils::IsSystemPrincipal(&aSubjectPrincipal)) {
continue;
}
@ -332,61 +334,33 @@ DataTransfer::GetTypes(ErrorResult& aRv) const
item->GetType(type);
if (item->Kind() == DataTransferItem::KIND_STRING || type.EqualsASCII(kFileMime)) {
// If the entry has kind KIND_STRING, we want to add it to the list.
if (NS_WARN_IF(!types->Add(type))) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
aTypes.AppendElement(type);
}
}
for (uint32_t i = 0; i < mItems->Length(); ++i) {
ErrorResult rv;
bool found = false;
DataTransferItem* item = mItems->IndexedGetter(i, found, rv);
if (!found || rv.Failed() || item->Kind() != DataTransferItem::KIND_FILE) {
rv.SuppressException();
DataTransferItem* item = mItems->IndexedGetter(i, found);
MOZ_ASSERT(found);
if (item->Kind() != DataTransferItem::KIND_FILE) {
continue;
}
if (NS_WARN_IF(!types->Add(NS_LITERAL_STRING("Files")))) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
aTypes.AppendElement(NS_LITERAL_STRING("Files"));
break;
}
return types.forget();
}
NS_IMETHODIMP
DataTransfer::GetTypes(nsISupports** aTypes)
{
if (NS_WARN_IF(!aTypes)) {
return NS_ERROR_FAILURE;
}
ErrorResult rv;
RefPtr<DOMStringList> types = GetTypes(rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
types.forget(aTypes);
return NS_OK;
}
void
DataTransfer::GetData(const nsAString& aFormat, nsAString& aData,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
// return an empty string if data for the format was not found
aData.Truncate();
nsCOMPtr<nsIVariant> data;
nsresult rv =
GetDataAtInternal(aFormat, 0, aSubjectPrincipal.value(),
GetDataAtInternal(aFormat, 0, &aSubjectPrincipal,
getter_AddRefs(data));
if (NS_FAILED(rv)) {
if (rv != NS_ERROR_DOM_INDEX_SIZE_ERR) {
@ -434,34 +408,22 @@ DataTransfer::GetData(const nsAString& aFormat, nsAString& aData,
}
}
NS_IMETHODIMP
DataTransfer::GetData(const nsAString& aFormat, nsAString& aData)
{
ErrorResult rv;
GetData(aFormat, aData, Some(nsContentUtils::SubjectPrincipal()), rv);
return rv.StealNSResult();
}
void
DataTransfer::SetData(const nsAString& aFormat, const nsAString& aData,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
RefPtr<nsVariantCC> variant = new nsVariantCC();
variant->SetAsAString(aData);
aRv = SetDataAtInternal(aFormat, variant, 0, aSubjectPrincipal.value());
aRv = SetDataAtInternal(aFormat, variant, 0, &aSubjectPrincipal);
}
void
DataTransfer::ClearData(const Optional<nsAString>& aFormat,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (mReadOnly) {
aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
return;
@ -648,13 +610,11 @@ void
DataTransfer::MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
uint32_t aIndex,
JS::MutableHandle<JS::Value> aRetval,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
nsCOMPtr<nsIVariant> data;
aRv = GetDataAtInternal(aFormat, aIndex, aSubjectPrincipal.value(),
aRv = GetDataAtInternal(aFormat, aIndex, &aSubjectPrincipal,
getter_AddRefs(data));
if (aRv.Failed()) {
return;
@ -693,6 +653,12 @@ DataTransfer::PrincipalMaySetData(const nsAString& aType,
return true;
}
void
DataTransfer::TypesListMayHaveChanged()
{
DataTransferBinding::ClearCachedTypesValue(this);
}
nsresult
DataTransfer::SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData,
uint32_t aIndex,
@ -734,26 +700,22 @@ DataTransfer::SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData,
void
DataTransfer::MozSetDataAt(JSContext* aCx, const nsAString& aFormat,
JS::Handle<JS::Value> aData, uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
nsCOMPtr<nsIVariant> data;
aRv = nsContentUtils::XPConnect()->JSValToVariant(aCx, aData,
getter_AddRefs(data));
if (!aRv.Failed()) {
aRv = SetDataAtInternal(aFormat, data, aIndex, aSubjectPrincipal.value());
aRv = SetDataAtInternal(aFormat, data, aIndex, &aSubjectPrincipal);
}
}
void
DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (mReadOnly) {
aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
return;
@ -788,7 +750,7 @@ DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
void
DataTransfer::MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(!mReadOnly);
@ -796,7 +758,6 @@ DataTransfer::MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
MOZ_ASSERT(aIndex == 0 ||
(mEventMessage != eCut && mEventMessage != eCopy &&
mEventMessage != ePaste));
MOZ_ASSERT(aSubjectPrincipal.isSome());
nsAutoString format;
GetRealFormat(aFormat, format);
@ -830,11 +791,9 @@ DataTransfer::SetDragImage(nsIDOMElement* aImage, int32_t aX, int32_t aY)
}
already_AddRefed<Promise>
DataTransfer::GetFilesAndDirectories(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
DataTransfer::GetFilesAndDirectories(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
nsCOMPtr<nsINode> parentNode = do_QueryInterface(mParent);
if (!parentNode) {
aRv.Throw(NS_ERROR_FAILURE);
@ -853,7 +812,7 @@ DataTransfer::GetFilesAndDirectories(const Maybe<nsIPrincipal*>& aSubjectPrincip
return nullptr;
}
RefPtr<FileList> files = mItems->Files(aSubjectPrincipal.value());
RefPtr<FileList> files = mItems->Files(&aSubjectPrincipal);
if (NS_WARN_IF(!files)) {
return nullptr;
}
@ -871,7 +830,7 @@ DataTransfer::GetFilesAndDirectories(const Maybe<nsIPrincipal*>& aSubjectPrincip
already_AddRefed<Promise>
DataTransfer::GetFiles(bool aRecursiveFlag,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
// Currently we don't support directories.
@ -1475,8 +1434,8 @@ DataTransfer::FillInExternalCustomTypes(uint32_t aIndex,
nsIPrincipal* aPrincipal)
{
RefPtr<DataTransferItem> item = new DataTransferItem(this,
NS_LITERAL_STRING(kCustomTypesMime));
item->SetKind(DataTransferItem::KIND_STRING);
NS_LITERAL_STRING(kCustomTypesMime),
DataTransferItem::KIND_STRING);
item->SetIndex(aIndex);
nsCOMPtr<nsIVariant> variant = item->DataNoSecurityCheck();

View File

@ -136,31 +136,32 @@ public:
void SetDragImage(Element& aElement, int32_t aX, int32_t aY,
ErrorResult& aRv);
already_AddRefed<DOMStringList> GetTypes(ErrorResult& rv) const;
void GetTypes(nsTArray<nsString>& aTypes,
nsIPrincipal& aSubjectPrincipal) const;
void GetData(const nsAString& aFormat, nsAString& aData,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
void SetData(const nsAString& aFormat, const nsAString& aData,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
void ClearData(const mozilla::dom::Optional<nsAString>& aFormat,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aRv);
already_AddRefed<FileList>
GetFiles(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
GetFiles(nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aRv);
already_AddRefed<Promise>
GetFilesAndDirectories(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
GetFilesAndDirectories(nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aRv);
already_AddRefed<Promise>
GetFiles(bool aRecursiveFlag,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
@ -181,17 +182,17 @@ public:
mozilla::ErrorResult& aRv) const;
void MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aRv);
void MozSetDataAt(JSContext* aCx, const nsAString& aFormat,
JS::Handle<JS::Value> aData, uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aRv);
void MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
uint32_t aIndex, JS::MutableHandle<JS::Value> aRetval,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aRv);
bool MozUserCancelled() const
@ -289,6 +290,11 @@ public:
nsIVariant* aData,
nsIPrincipal* aPrincipal);
// Notify the DataTransfer that the list returned from GetTypes may have
// changed. This can happen due to items we care about for purposes of
// GetTypes being added or removed or changing item kinds.
void TypesListMayHaveChanged();
protected:
// caches text and uri-list data formats that exist in the drag service or
@ -321,7 +327,7 @@ protected:
nsIPrincipal* aPrincipal);
void MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aRv);
nsCOMPtr<nsISupports> mParent;

View File

@ -73,12 +73,6 @@ DataTransferItem::Clone(DataTransfer* aDataTransfer) const
return it.forget();
}
void
DataTransferItem::SetType(const nsAString& aType)
{
mType = aType;
}
void
DataTransferItem::SetData(nsIVariant* aData)
{
@ -230,26 +224,23 @@ DataTransferItem::FillInExternalData()
SetData(variant);
#ifdef DEBUG
if (oldKind != Kind()) {
NS_WARNING("Clipboard data provided by the OS does not match predicted kind");
mDataTransfer->TypesListMayHaveChanged();
}
#endif
}
already_AddRefed<File>
DataTransferItem::GetAsFile(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
DataTransferItem::GetAsFile(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (mKind != KIND_FILE) {
return nullptr;
}
// This is done even if we have an mCachedFile, as it performs the necessary
// permissions checks to ensure that we are allowed to access this type.
nsCOMPtr<nsIVariant> data = Data(aSubjectPrincipal.value(), aRv);
nsCOMPtr<nsIVariant> data = Data(&aSubjectPrincipal, aRv);
if (NS_WARN_IF(!data || aRv.Failed())) {
return nullptr;
}
@ -283,11 +274,9 @@ DataTransferItem::GetAsFile(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
}
already_AddRefed<FileSystemEntry>
DataTransferItem::GetAsEntry(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
DataTransferItem::GetAsEntry(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
RefPtr<File> file = GetAsFile(aSubjectPrincipal, aRv);
if (NS_WARN_IF(aRv.Failed()) || !file) {
return nullptr;
@ -386,11 +375,9 @@ DataTransferItem::CreateFileFromInputStream(nsIInputStream* aStream)
void
DataTransferItem::GetAsString(FunctionStringCallback* aCallback,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (!aCallback || mKind != KIND_STRING) {
return;
}
@ -398,7 +385,7 @@ DataTransferItem::GetAsString(FunctionStringCallback* aCallback,
// Theoretically this should be done inside of the runnable, as it might be an
// expensive operation on some systems, however we wouldn't get access to the
// NS_ERROR_DOM_SECURITY_ERROR messages which may be raised by this method.
nsCOMPtr<nsIVariant> data = Data(aSubjectPrincipal.value(), aRv);
nsCOMPtr<nsIVariant> data = Data(&aSubjectPrincipal, aRv);
if (NS_WARN_IF(!data || aRv.Failed())) {
return;
}

View File

@ -35,10 +35,11 @@ public:
KIND_OTHER,
};
DataTransferItem(DataTransfer* aDataTransfer, const nsAString& aType)
DataTransferItem(DataTransfer* aDataTransfer, const nsAString& aType,
eKind aKind = KIND_OTHER)
: mIndex(0)
, mChromeOnly(false)
, mKind(KIND_OTHER)
, mKind(aKind)
, mType(aType)
, mDataTransfer(aDataTransfer)
{
@ -49,9 +50,8 @@ public:
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
// NOTE: This accesses the subject principal, and should not be called from C++
void GetAsString(FunctionStringCallback* aCallback,
const Maybe<nsIPrincipal*>& aPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
void GetKind(nsAString& aKind) const
@ -73,22 +73,17 @@ public:
{
aType = mType;
}
void SetType(const nsAString& aType);
eKind Kind() const
{
return mKind;
}
void SetKind(eKind aKind)
{
mKind = aKind;
}
already_AddRefed<File>
GetAsFile(const Maybe<nsIPrincipal*>& aSubjectPrincipal, ErrorResult& aRv);
GetAsFile(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
already_AddRefed<FileSystemEntry>
GetAsEntry(const Maybe<nsIPrincipal*>& aSubjectPrincipal, ErrorResult& aRv);
GetAsEntry(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
DataTransfer* GetParentObject() const
{
@ -106,6 +101,9 @@ public:
already_AddRefed<nsIVariant> DataNoSecurityCheck();
already_AddRefed<nsIVariant> Data(nsIPrincipal* aPrincipal, ErrorResult& aRv);
// Note: This can modify the mKind. Callers of this method must let the
// relevant DataTransfer know, because its types list can change as a result.
void SetData(nsIVariant* aData);
uint32_t Index() const
@ -138,7 +136,7 @@ private:
bool mChromeOnly;
eKind mKind;
nsString mType;
const nsString mType;
nsCOMPtr<nsIVariant> mData;
nsCOMPtr<nsIPrincipal> mPrincipal;
RefPtr<DataTransfer> mDataTransfer;

View File

@ -82,11 +82,9 @@ DataTransferItemList::Clone(DataTransfer* aDataTransfer) const
void
DataTransferItemList::Remove(uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (mDataTransfer->IsReadOnly()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
@ -101,7 +99,7 @@ DataTransferItemList::Remove(uint32_t aIndex,
}
DataTransferItem*
DataTransferItemList::IndexedGetter(uint32_t aIndex, bool& aFound, ErrorResult& aRv) const
DataTransferItemList::IndexedGetter(uint32_t aIndex, bool& aFound) const
{
if (aIndex >= mItems.Length()) {
aFound = false;
@ -126,11 +124,9 @@ DataTransferItemList::MozItemCount() const
}
void
DataTransferItemList::Clear(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
DataTransferItemList::Clear(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (NS_WARN_IF(mDataTransfer->IsReadOnly())) {
return;
}
@ -149,11 +145,9 @@ DataTransferItemList::Clear(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
DataTransferItem*
DataTransferItemList::Add(const nsAString& aData,
const nsAString& aType,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (NS_WARN_IF(mDataTransfer->IsReadOnly())) {
return nullptr;
}
@ -163,8 +157,7 @@ DataTransferItemList::Add(const nsAString& aData,
nsAutoString format;
mDataTransfer->GetRealFormat(aType, format);
if (!DataTransfer::PrincipalMaySetData(format, data,
aSubjectPrincipal.value())) {
if (!DataTransfer::PrincipalMaySetData(format, data, &aSubjectPrincipal)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr;
}
@ -172,7 +165,7 @@ DataTransferItemList::Add(const nsAString& aData,
// We add the textual data to index 0. We set aInsertOnly to true, as we don't
// want to update an existing entry if it is already present, as per the spec.
RefPtr<DataTransferItem> item =
SetDataWithPrincipal(format, data, 0, aSubjectPrincipal.value(),
SetDataWithPrincipal(format, data, 0, &aSubjectPrincipal,
/* aInsertOnly = */ true,
/* aHidden = */ false,
aRv);
@ -186,11 +179,9 @@ DataTransferItemList::Add(const nsAString& aData,
DataTransferItem*
DataTransferItemList::Add(File& aData,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (mDataTransfer->IsReadOnly()) {
return nullptr;
}
@ -202,8 +193,7 @@ DataTransferItemList::Add(File& aData,
nsAutoString type;
aData.GetType(type);
if (!DataTransfer::PrincipalMaySetData(type, data,
aSubjectPrincipal.value())) {
if (!DataTransfer::PrincipalMaySetData(type, data, &aSubjectPrincipal)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr;
}
@ -213,7 +203,7 @@ DataTransferItemList::Add(File& aData,
// the internal specced layout.
uint32_t index = mIndexedItems.Length();
RefPtr<DataTransferItem> item =
SetDataWithPrincipal(type, data, index, aSubjectPrincipal.value(),
SetDataWithPrincipal(type, data, index, &aSubjectPrincipal,
/* aInsertOnly = */ true,
/* aHidden = */ false,
aRv);
@ -272,11 +262,9 @@ DataTransferItemList::Files(nsIPrincipal* aPrincipal)
void
DataTransferItemList::MozRemoveByTypeAt(const nsAString& aType,
uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (NS_WARN_IF(mDataTransfer->IsReadOnly() ||
aIndex >= mIndexedItems.Length())) {
return;
@ -370,6 +358,10 @@ DataTransferItemList::SetDataWithPrincipal(const nsAString& aType,
DataTransferItem::eKind oldKind = item->Kind();
item->SetData(aData);
if (oldKind != item->Kind()) {
// Types list may have changed, even if aIndex == 0.
mDataTransfer->TypesListMayHaveChanged();
}
if (aIndex != 0) {
// If the item changes from being a file to not a file or vice-versa,
@ -433,9 +425,15 @@ DataTransferItemList::AppendNewItem(uint32_t aIndex,
// adding to is 0, or the item we are adding is a file. If we add an item
// which is not a file to a non-zero index, invariants could be broken.
// (namely the invariant that there are not 2 non-file entries in the items
// array with the same type)
if (!aHidden && (item->Kind() == DataTransferItem::KIND_FILE || aIndex == 0)) {
mItems.AppendElement(item);
// array with the same type).
//
// We also want to update our DataTransfer's type list any time we're adding a
// KIND_FILE item, or an item at index 0.
if (item->Kind() == DataTransferItem::KIND_FILE || aIndex == 0) {
if (!aHidden) {
mItems.AppendElement(item);
}
mDataTransfer->TypesListMayHaveChanged();
}
return item;
@ -475,6 +473,7 @@ DataTransferItemList::ClearAllItems()
mItems.Clear();
mIndexedItems.Clear();
mIndexedItems.SetLength(1);
mDataTransfer->TypesListMayHaveChanged();
// Re-generate files (into an empty list)
RegenerateFiles();
@ -484,7 +483,7 @@ void
DataTransferItemList::ClearDataHelper(DataTransferItem* aItem,
uint32_t aIndexHint,
uint32_t aMozOffsetHint,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aItem);
@ -492,22 +491,19 @@ DataTransferItemList::ClearDataHelper(DataTransferItem* aItem,
return;
}
if (aItem->Principal() && aSubjectPrincipal.isSome() &&
!aSubjectPrincipal.value()->Subsumes(aItem->Principal())) {
if (aItem->Principal() && !aSubjectPrincipal.Subsumes(aItem->Principal())) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
// Check if the aIndexHint is actually the index, and then remove the item
// from aItems
ErrorResult rv;
bool found;
if (IndexedGetter(aIndexHint, found, rv) == aItem) {
if (IndexedGetter(aIndexHint, found) == aItem) {
mItems.RemoveElementAt(aIndexHint);
} else {
mItems.RemoveElement(aItem);
}
rv.SuppressException();
// Check if the aMozIndexHint and aMozOffsetHint are actually the index and
// offset, and then remove them from mIndexedItems
@ -519,6 +515,8 @@ DataTransferItemList::ClearDataHelper(DataTransferItem* aItem,
items.RemoveElement(aItem);
}
mDataTransfer->TypesListMayHaveChanged();
// Check if we should remove the index. We never remove index 0.
if (items.Length() == 0 && aItem->Index() != 0) {
mIndexedItems.RemoveElementAt(aItem->Index());
@ -564,15 +562,13 @@ DataTransferItemList::GenerateFiles(FileList* aFiles,
MOZ_ASSERT(aFilesPrincipal);
uint32_t count = Length();
for (uint32_t i = 0; i < count; i++) {
ErrorResult rv;
bool found;
RefPtr<DataTransferItem> item = IndexedGetter(i, found, rv);
if (NS_WARN_IF(!found || rv.Failed())) {
continue;
}
RefPtr<DataTransferItem> item = IndexedGetter(i, found);
MOZ_ASSERT(found);
if (item->Kind() == DataTransferItem::KIND_FILE) {
RefPtr<File> file = item->GetAsFile(Some(aFilesPrincipal), rv);
IgnoredErrorResult rv;
RefPtr<File> file = item->GetAsFile(*aFilesPrincipal, rv);
if (NS_WARN_IF(rv.Failed() || !file)) {
continue;
}

View File

@ -51,25 +51,24 @@ public:
};
DataTransferItem* Add(const nsAString& aData, const nsAString& aType,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& rv);
DataTransferItem* Add(File& aData,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
void Remove(uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
DataTransferItem* IndexedGetter(uint32_t aIndex, bool& aFound,
ErrorResult& aRv) const;
DataTransferItem* IndexedGetter(uint32_t aIndex, bool& aFound) const;
DataTransfer* GetParentObject() const
{
return mDataTransfer;
}
void Clear(const Maybe<nsIPrincipal*>& aSubjectPrincipal, ErrorResult& aRv);
void Clear(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
already_AddRefed<DataTransferItem>
SetDataWithPrincipal(const nsAString& aType, nsIVariant* aData,
@ -80,7 +79,7 @@ public:
// Moz-style helper methods for interacting with the stored data
void MozRemoveByTypeAt(const nsAString& aType, uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
DataTransferItem* MozItemByTypeAt(const nsAString& aType, uint32_t aIndex);
const nsTArray<RefPtr<DataTransferItem>>* MozItemsAt(uint32_t aIndex);
@ -96,7 +95,7 @@ public:
private:
void ClearDataHelper(DataTransferItem* aItem, uint32_t aIndexHint,
uint32_t aMozOffsetHint,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
DataTransferItem* AppendNewItem(uint32_t aIndex, const nsAString& aType,
nsIVariant* aData, nsIPrincipal* aPrincipal,
@ -111,7 +110,18 @@ private:
RefPtr<FileList> mFiles;
// The principal for which mFiles is cached
nsCOMPtr<nsIPrincipal> mFilesPrincipal;
// mItems is the list of items that corresponds to the spec concept of a
// DataTransferItemList. That is, this is the thing the spec's indexed getter
// operates on. The items in here are a subset of the items present in the
// arrays that live in mIndexedItems.
nsTArray<RefPtr<DataTransferItem>> mItems;
// mIndexedItems represents all our items. For any given index, all items at
// that index have different types in the GetType() sense. That means that
// representing multiple items with the same type (e.g. multiple files)
// requires using multiple indices.
//
// There is always a (possibly empty) list of items at index 0, so
// mIndexedItems.Length() >= 1 at all times.
nsTArray<nsTArray<RefPtr<DataTransferItem>>> mIndexedItems;
};

View File

@ -118,7 +118,7 @@ function doDragStartSelection(event)
gDataTransfer = dt;
var types = dt.types;
is(types instanceof DOMStringList, true, "initial types is a DOMStringList");
ok(Array.isArray(types), "initial types is an Array");
checkTypes(dt, ["text/_moz_htmlcontext", "text/_moz_htmlinfo", "text/html", "text/plain"], 0, "initial selection");
is(dt.getData("text/plain"), "This is a draggable bit of text.", "initial selection text/plain");
@ -148,7 +148,7 @@ function test_DataTransfer(dt)
is(dt.mozItemCount, 0, "empty itemCount");
var types = dt.types;
is(types instanceof DOMStringList, true, "empty types is a DOMStringList");
ok(Array.isArray(types), "empty types is an Array");
checkTypes(dt, [], 0, "empty");
is(dt.getData("text/plain"), "", "empty data is empty");

View File

@ -168,7 +168,7 @@ public:
GetEnumAttr(nsGkAtoms::referrerpolicy, EmptyCString().get(), aReferrer);
}
nsIDocument*
GetSVGDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
GetSVGDocument(nsIPrincipal& aSubjectPrincipal)
{
return GetContentDocument(aSubjectPrincipal);
}

View File

@ -2841,11 +2841,9 @@ HTMLInputElement::MozIsTextField(bool aExcludePassword, bool* aResult)
void
HTMLInputElement::SetUserInput(const nsAString& aInput,
const mozilla::Maybe<nsIPrincipal*>& aPrincipal) {
MOZ_ASSERT(aPrincipal.isSome());
nsIPrincipal& aSubjectPrincipal) {
if (mType == NS_FORM_INPUT_FILE &&
!nsContentUtils::IsSystemPrincipal(aPrincipal.value())) {
!nsContentUtils::IsSystemPrincipal(&aSubjectPrincipal)) {
return;
}

View File

@ -821,7 +821,7 @@ public:
nsIEditor* GetEditor();
void SetUserInput(const nsAString& aInput,
const mozilla::Maybe<nsIPrincipal*>& aPrincipal);
nsIPrincipal& aSubjectPrincipal);
// XPCOM GetPhonetic() is OK

View File

@ -466,13 +466,13 @@ HTMLObjectElement::GetContentDocument(nsIDOMDocument **aContentDocument)
NS_ENSURE_ARG_POINTER(aContentDocument);
nsCOMPtr<nsIDOMDocument> domDoc =
do_QueryInterface(GetContentDocument(Some(nsContentUtils::SubjectPrincipal())));
do_QueryInterface(GetContentDocument(*nsContentUtils::SubjectPrincipal()));
domDoc.forget(aContentDocument);
return NS_OK;
}
nsPIDOMWindowOuter*
HTMLObjectElement::GetContentWindow(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
HTMLObjectElement::GetContentWindow(nsIPrincipal& aSubjectPrincipal)
{
nsIDocument* doc = GetContentDocument(aSubjectPrincipal);
if (doc) {

View File

@ -158,7 +158,7 @@ public:
using nsObjectLoadingContent::GetContentDocument;
nsPIDOMWindowOuter*
GetContentWindow(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal);
GetContentWindow(nsIPrincipal& aSubjectPrincipal);
using nsIConstraintValidation::CheckValidity;
using nsIConstraintValidation::ReportValidity;
@ -239,7 +239,7 @@ public:
}
nsIDocument*
GetSVGDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
GetSVGDocument(nsIPrincipal& aSubjectPrincipal)
{
return GetContentDocument(aSubjectPrincipal);
}

View File

@ -188,7 +188,7 @@ public:
// align covered by <applet>
// name covered by <applet>
nsIDocument*
GetSVGDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
GetSVGDocument(nsIPrincipal& aSubjectPrincipal)
{
return GetContentDocument(aSubjectPrincipal);
}

View File

@ -80,13 +80,13 @@ nsGenericHTMLFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
{
NS_PRECONDITION(aContentDocument, "Null out param");
nsCOMPtr<nsIDOMDocument> document =
do_QueryInterface(GetContentDocument(Some(nsContentUtils::SubjectPrincipal())));
do_QueryInterface(GetContentDocument(*nsContentUtils::SubjectPrincipal()));
document.forget(aContentDocument);
return NS_OK;
}
nsIDocument*
nsGenericHTMLFrameElement::GetContentDocument(const Maybe<nsIPrincipal*>& aSubjectPrincipal)
nsGenericHTMLFrameElement::GetContentDocument(nsIPrincipal& aSubjectPrincipal)
{
nsCOMPtr<nsPIDOMWindowOuter> win = GetContentWindow();
if (!win) {
@ -99,8 +99,7 @@ nsGenericHTMLFrameElement::GetContentDocument(const Maybe<nsIPrincipal*>& aSubje
}
// Return null for cross-origin contentDocument.
if (!aSubjectPrincipal.value()
->SubsumesConsideringDomain(doc->NodePrincipal())) {
if (!aSubjectPrincipal.SubsumesConsideringDomain(doc->NodePrincipal())) {
return nullptr;
}
return doc;

View File

@ -102,8 +102,7 @@ protected:
// it makes sense.
void EnsureFrameLoader();
nsresult LoadSrc();
nsIDocument*
GetContentDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal);
nsIDocument* GetContentDocument(nsIPrincipal& aSubjectPrincipal);
nsresult GetContentDocument(nsIDOMDocument** aContentDocument);
already_AddRefed<nsPIDOMWindowOuter> GetContentWindow();

View File

@ -2841,12 +2841,20 @@ nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode)
return rv.StealNSResult();
}
void
nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& rv)
{
SetDesignMode(aDesignMode, Some(&aSubjectPrincipal), rv);
}
void
nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
ErrorResult& rv)
{
if (!nsContentUtils::LegacyIsCallerNativeCode() &&
if (aSubjectPrincipal.isSome() &&
!aSubjectPrincipal.value()->Subsumes(NodePrincipal())) {
rv.Throw(NS_ERROR_DOM_PROP_ACCESS_DENIED);
return;

View File

@ -211,10 +211,13 @@ public:
void Writeln(JSContext* cx, const mozilla::dom::Sequence<nsString>& aText,
mozilla::ErrorResult& rv);
void GetDesignMode(nsAString& aDesignMode,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
nsIPrincipal& aSubjectPrincipal)
{
GetDesignMode(aDesignMode);
}
void SetDesignMode(const nsAString& aDesignMode,
nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& rv);
void SetDesignMode(const nsAString& aDesignMode,
const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
mozilla::ErrorResult& rv);

View File

@ -66,19 +66,6 @@ interface nsIDOMDataTransfer : nsISupports
*/
readonly attribute nsIDOMFileList files;
/**
* Holds a list of the format types of the data that is stored for the first
* item, in the same order the data was added. An empty list will be
* returned if no data was added.
*/
readonly attribute nsISupports types;
/**
* Retrieves the data for a given format, or an empty string if data for
* that format does not exist or the data transfer contains no data.
*/
DOMString getData(in DOMString format);
/**
* Set the image to be used for dragging if a custom one is desired. Most of
* the time, this would not be set, as a default image is created from the

View File

@ -307,7 +307,8 @@ HangMonitorChild::InterruptCallback()
if (forcePaint) {
RefPtr<TabChild> tabChild = TabChild::FindTabChild(forcePaintTab);
if (tabChild) {
JS::AutoAssertOnGC aaogc(mContext);
JS::AutoAssertOnGC nogc(mContext);
JS::AutoAssertOnBarrier nobarrier(mContext);
tabChild->ForcePaint(forcePaintEpoch);
}
}
@ -389,6 +390,7 @@ HangMonitorChild::RecvForcePaint(const TabId& aTabId, const uint64_t& aLayerObse
}
JS_RequestInterruptCallback(mContext);
JS::RequestGCInterruptCallback(mContext);
return true;
}
@ -1187,6 +1189,7 @@ mozilla::CreateHangMonitorChild(mozilla::ipc::Transport* aTransport,
JSContext* cx = danger::GetJSContext();
JS_AddInterruptCallback(cx, InterruptCallback);
JS::AddGCInterruptCallback(cx, InterruptCallback);
ProcessHangMonitor* monitor = ProcessHangMonitor::GetOrCreate();
HangMonitorChild* child = new HangMonitorChild(monitor);

View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<script>
function boom()
{
var ac = new window.AudioContext("publicnotification");
setTimeout(function() {
document.documentElement.removeAttribute("class");
var htmlAudio = new Audio();
var stream = htmlAudio.mozCaptureStreamUntilEnded();
ac.createMediaStreamSource(stream);
}, 0);
}
</script>
</head>
<body onload="boom();">
</body>
</html>

View File

@ -81,6 +81,7 @@ load 1157994.html
skip-if(!B2G) load 1158427.html
load 1185176.html
load 1185192.html
load 1223670.html
load 1228484.html
load 1304948.html
load analyser-channels-1.html

View File

@ -67,12 +67,10 @@ DOMStorage::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
}
uint32_t
DOMStorage::GetLength(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
DOMStorage::GetLength(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (!CanUseStorage(nullptr, aSubjectPrincipal, this)) {
if (!CanUseStorage(aSubjectPrincipal)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return 0;
}
@ -84,12 +82,10 @@ DOMStorage::GetLength(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
void
DOMStorage::Key(uint32_t aIndex, nsAString& aResult,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (!CanUseStorage(nullptr, aSubjectPrincipal, this)) {
if (!CanUseStorage(aSubjectPrincipal)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
@ -99,12 +95,10 @@ DOMStorage::Key(uint32_t aIndex, nsAString& aResult,
void
DOMStorage::GetItem(const nsAString& aKey, nsAString& aResult,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (!CanUseStorage(nullptr, aSubjectPrincipal, this)) {
if (!CanUseStorage(aSubjectPrincipal)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
@ -114,12 +108,10 @@ DOMStorage::GetItem(const nsAString& aKey, nsAString& aResult,
void
DOMStorage::SetItem(const nsAString& aKey, const nsAString& aData,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (!CanUseStorage(nullptr, aSubjectPrincipal, this)) {
if (!CanUseStorage(aSubjectPrincipal)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
@ -144,12 +136,10 @@ DOMStorage::SetItem(const nsAString& aKey, const nsAString& aData,
void
DOMStorage::RemoveItem(const nsAString& aKey,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (!CanUseStorage(nullptr, aSubjectPrincipal, this)) {
if (!CanUseStorage(aSubjectPrincipal)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
@ -166,12 +156,10 @@ DOMStorage::RemoveItem(const nsAString& aKey,
}
void
DOMStorage::Clear(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
DOMStorage::Clear(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (!CanUseStorage(nullptr, aSubjectPrincipal, this)) {
if (!CanUseStorage(aSubjectPrincipal)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
@ -245,11 +233,8 @@ DOMStorage::BroadcastChangeNotification(const nsSubstring& aKey,
static const char kPermissionType[] = "cookie";
static const char kStorageEnabled[] = "dom.storage.enabled";
// static, public
bool
DOMStorage::CanUseStorage(nsPIDOMWindowInner* aWindow,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
DOMStorage* aStorage)
DOMStorage::CanUseStorage(nsIPrincipal& aSubjectPrincipal)
{
// This method is responsible for correct setting of mIsSessionOnly.
@ -257,25 +242,15 @@ DOMStorage::CanUseStorage(nsPIDOMWindowInner* aWindow,
return false;
}
nsContentUtils::StorageAccess access = nsContentUtils::StorageAccess::eDeny;
if (aWindow) {
access = nsContentUtils::StorageAllowedForWindow(aWindow);
} else if (aStorage) {
access = nsContentUtils::StorageAllowedForPrincipal(aStorage->mPrincipal);
}
nsContentUtils::StorageAccess access =
nsContentUtils::StorageAllowedForPrincipal(mPrincipal);
if (access == nsContentUtils::StorageAccess::eDeny) {
return false;
}
if (aStorage) {
aStorage->mIsSessionOnly = access <= nsContentUtils::StorageAccess::eSessionScoped;
MOZ_ASSERT(aSubjectPrincipal.isSome());
return aStorage->CanAccess(aSubjectPrincipal.value());
}
return true;
mIsSessionOnly = access <= nsContentUtils::StorageAccess::eSessionScoped;
return CanAccess(&aSubjectPrincipal);
}
DOMStorage::StorageType
@ -320,8 +295,7 @@ DOMStorage::CanAccess(nsIPrincipal* aPrincipal)
void
DOMStorage::GetSupportedNames(nsTArray<nsString>& aKeys)
{
if (!CanUseStorage(nullptr, Some(nsContentUtils::SubjectPrincipal()),
this)) {
if (!CanUseStorage(*nsContentUtils::SubjectPrincipal())) {
// return just an empty array
aKeys.Clear();
return;

View File

@ -70,21 +70,21 @@ public:
return mWindow;
}
uint32_t GetLength(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
uint32_t GetLength(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
void Key(uint32_t aIndex, nsAString& aResult,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
void GetItem(const nsAString& aKey, nsAString& aResult,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
void GetSupportedNames(nsTArray<nsString>& aKeys);
void NamedGetter(const nsAString& aKey, bool& aFound, nsAString& aResult,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
GetItem(aKey, aResult, aSubjectPrincipal, aRv);
@ -92,22 +92,22 @@ public:
}
void SetItem(const nsAString& aKey, const nsAString& aValue,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
void NamedSetter(const nsAString& aKey, const nsAString& aValue,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
SetItem(aKey, aValue, aSubjectPrincipal, aRv);
}
void RemoveItem(const nsAString& aKey,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
void NamedDeleter(const nsAString& aKey, bool& aFound,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
RemoveItem(aKey, aSubjectPrincipal, aRv);
@ -115,20 +115,9 @@ public:
aFound = !aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION);
}
void Clear(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
void Clear(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
// The method checks whether the caller can use a storage.
// CanUseStorage is called before any DOM initiated operation
// on a storage is about to happen and ensures that the storage's
// session-only flag is properly set according the current settings.
// It is an optimization since the privileges check and session only
// state determination are complex and share the code (comes hand in
// hand together).
static bool CanUseStorage(nsPIDOMWindowInner* aWindow,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
DOMStorage* aStorage = nullptr);
bool IsPrivate() const;
bool IsSessionOnly() const { return mIsSessionOnly; }
@ -138,6 +127,16 @@ public:
return mCache == aOther->mCache;
}
protected:
// The method checks whether the caller can use a storage.
// CanUseStorage is called before any DOM initiated operation
// on a storage is about to happen and ensures that the storage's
// session-only flag is properly set according the current settings.
// It is an optimization since the privileges check and session only
// state determination are complex and share the code (comes hand in
// hand together).
bool CanUseStorage(nsIPrincipal& aSubjectPrincipal);
private:
~DOMStorage();

View File

@ -17,8 +17,8 @@ interface DataTransfer {
[Throws]
void setDragImage(Element image, long x, long y);
[Throws]
readonly attribute DOMStringList types;
[Pure, Cached, Frozen, NeedsSubjectPrincipal]
readonly attribute sequence<DOMString> types;
[Throws, NeedsSubjectPrincipal]
DOMString getData(DOMString format);
[Throws, NeedsSubjectPrincipal]

View File

@ -9,7 +9,6 @@
interface DataTransferItemList {
readonly attribute unsigned long length;
[Throws]
getter DataTransferItem (unsigned long index);
[Throws, NeedsSubjectPrincipal]
DataTransferItem? add(DOMString data, DOMString type);

View File

@ -109,7 +109,7 @@ Window implements WindowSessionStorage;
// http://www.whatwg.org/specs/web-apps/current-work/
[NoInterfaceObject]
interface WindowLocalStorage {
[Throws, NeedsSubjectPrincipal] readonly attribute Storage? localStorage;
[Throws] readonly attribute Storage? localStorage;
};
Window implements WindowLocalStorage;

View File

@ -934,19 +934,16 @@ EditorEventListener::CanDrop(nsIDOMDragEvent* aEvent)
nsCOMPtr<DataTransfer> dataTransfer = do_QueryInterface(domDataTransfer);
NS_ENSURE_TRUE(dataTransfer, false);
ErrorResult err;
RefPtr<DOMStringList> types = dataTransfer->GetTypes(err);
if (NS_WARN_IF(err.Failed())) {
return false;
}
nsTArray<nsString> types;
dataTransfer->GetTypes(types, *nsContentUtils::GetSystemPrincipal());
// Plaintext editors only support dropping text. Otherwise, HTML and files
// can be dropped as well.
if (!types->Contains(NS_LITERAL_STRING(kTextMime)) &&
!types->Contains(NS_LITERAL_STRING(kMozTextInternal)) &&
if (!types.Contains(NS_LITERAL_STRING(kTextMime)) &&
!types.Contains(NS_LITERAL_STRING(kMozTextInternal)) &&
(mEditorBase->IsPlaintextEditor() ||
(!types->Contains(NS_LITERAL_STRING(kHTMLMime)) &&
!types->Contains(NS_LITERAL_STRING(kFileMime))))) {
(!types.Contains(NS_LITERAL_STRING(kHTMLMime)) &&
!types.Contains(NS_LITERAL_STRING(kFileMime))))) {
return false;
}

View File

@ -484,12 +484,23 @@ extern JS_PUBLIC_API(size_t)
GetGCNumber();
/**
* Assert if a GC occurs while this class is live. This class does not disable
* the static rooting hazard analysis.
* Pass a subclass of this "abstract" class to callees to require that they
* never GC. Subclasses can use assertions or the hazard analysis to ensure no
* GC happens.
*/
class JS_PUBLIC_API(AutoAssertOnGC)
class JS_PUBLIC_API(AutoRequireNoGC)
{
protected:
AutoRequireNoGC() {}
~AutoRequireNoGC() {}
};
/**
* Release assert if a GC occurs while this class is live. This class does
* not disable the static rooting hazard analysis.
*/
class JS_PUBLIC_API(AutoAssertOnGC) : public AutoRequireNoGC
{
#ifdef DEBUG
js::gc::GCRuntime* gc;
size_t gcNumber;
@ -497,16 +508,6 @@ class JS_PUBLIC_API(AutoAssertOnGC)
AutoAssertOnGC();
explicit AutoAssertOnGC(JSContext* cx);
~AutoAssertOnGC();
static void VerifyIsSafeToGC(JSRuntime* rt);
#else
public:
AutoAssertOnGC() {}
explicit AutoAssertOnGC(JSContext* cx) {}
~AutoAssertOnGC() {}
static void VerifyIsSafeToGC(JSRuntime* rt) {}
#endif
};
/**
@ -531,6 +532,20 @@ class JS_PUBLIC_API(AutoAssertNoAlloc)
#endif
};
/**
* Assert if a GC barrier is invoked while this class is live. This class does
* not disable the static rooting hazard analysis.
*/
class JS_PUBLIC_API(AutoAssertOnBarrier)
{
JSContext* context;
bool prev;
public:
explicit AutoAssertOnBarrier(JSContext* cx);
~AutoAssertOnBarrier();
};
/**
* Disable the static rooting hazard analysis in the live region and assert if
* any allocation that could potentially trigger a GC occurs while this guard
@ -575,13 +590,24 @@ class JS_PUBLIC_API(AutoAssertGCCallback) : public AutoSuppressGCAnalysis
* internal pointers to GC things where the GC thing itself may not be present
* for the static analysis: e.g. acquiring inline chars from a JSString* on the
* heap.
*
* We only do the assertion checking in DEBUG builds.
*/
#ifdef DEBUG
class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoAssertOnGC
{
public:
AutoCheckCannotGC() : AutoAssertOnGC() {}
explicit AutoCheckCannotGC(JSContext* cx) : AutoAssertOnGC(cx) {}
} JS_HAZ_GC_INVALIDATED;
#else
class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoRequireNoGC
{
public:
AutoCheckCannotGC() {}
explicit AutoCheckCannotGC(JSContext* cx) {}
} JS_HAZ_GC_INVALIDATED;
#endif
/**
* Unsets the gray bit for anything reachable from |thing|. |kind| should not be
@ -609,6 +635,7 @@ ExposeGCThingToActiveJS(JS::GCCellPtr thing)
if (IsInsideNursery(thing.asCell()))
return;
JS::shadow::Runtime* rt = detail::GetGCThingRuntime(thing.unsafeAsUIntPtr());
MOZ_DIAGNOSTIC_ASSERT(rt->allowGCBarriers());
if (IsIncrementalBarrierNeededOnTenuredGCThing(rt, thing))
JS::IncrementalReferenceBarrier(thing);
else if (JS::GCThingIsMarkedGray(thing))
@ -619,6 +646,7 @@ static MOZ_ALWAYS_INLINE void
MarkGCThingAsLive(JSRuntime* aRt, JS::GCCellPtr thing)
{
JS::shadow::Runtime* rt = JS::shadow::Runtime::asShadowRuntime(aRt);
MOZ_DIAGNOSTIC_ASSERT(rt->allowGCBarriers());
/*
* Any object in the nursery will not be freed during any GC running at that time.
*/
@ -676,6 +704,18 @@ PokeGC(JSContext* cx);
extern JS_FRIEND_API(void)
NotifyDidPaint(JSContext* cx);
// GC Interrupt callbacks are run during GC. You should not run JS code or use
// the JS engine at all while the callback is running. Otherwise they resemble
// normal JS interrupt callbacks.
typedef bool
(* GCInterruptCallback)(JSContext* cx);
extern JS_FRIEND_API(bool)
AddGCInterruptCallback(JSContext* cx, GCInterruptCallback callback);
extern JS_FRIEND_API(void)
RequestGCInterruptCallback(JSContext* cx);
} /* namespace JS */
#endif /* js_GCAPI_h */

View File

@ -7,6 +7,8 @@
#ifndef js_SliceBudget_h
#define js_SliceBudget_h
#include "mozilla/Atomics.h"
#include <stdint.h>
namespace js {
@ -36,7 +38,7 @@ class JS_PUBLIC_API(SliceBudget)
static const int64_t unlimitedDeadline = INT64_MAX;
static const intptr_t unlimitedStartCounter = INTPTR_MAX;
bool checkOverBudget();
bool checkOverBudget(JSContext* maybeCx);
SliceBudget();
@ -48,7 +50,7 @@ class JS_PUBLIC_API(SliceBudget)
WorkBudget workBudget;
int64_t deadline; /* in microseconds */
intptr_t counter;
mozilla::Atomic<intptr_t, mozilla::Relaxed> counter;
static const intptr_t CounterReset = 1000;
@ -64,19 +66,44 @@ class JS_PUBLIC_API(SliceBudget)
/* Instantiate as SliceBudget(WorkBudget(n)). */
explicit SliceBudget(WorkBudget work);
// Need an explicit copy constructor because Atomic fails to provide one.
SliceBudget(const SliceBudget& other)
: timeBudget(other.timeBudget),
workBudget(other.workBudget),
deadline(other.deadline),
counter(other.counter)
{}
// Need an explicit operator= because Atomic fails to provide one.
SliceBudget& operator=(const SliceBudget& other) {
timeBudget = other.timeBudget;
workBudget = other.workBudget;
deadline = other.deadline;
counter = intptr_t(other.counter);
return *this;
}
void makeUnlimited() {
deadline = unlimitedDeadline;
counter = unlimitedStartCounter;
}
// Request that checkOverBudget be called the next time isOverBudget is
// called.
void requestFullCheck() {
counter = 0;
}
void step(intptr_t amt = 1) {
counter -= amt;
}
bool isOverBudget() {
// Only need to pass maybeCx if the GC interrupt callback should be checked
// (and possibly invoked).
bool isOverBudget(JSContext* maybeCx = nullptr) {
if (counter > 0)
return false;
return checkOverBudget();
return checkOverBudget(maybeCx);
}
bool isWorkBudget() const { return deadline == 0; }

View File

@ -190,7 +190,7 @@ template bool js::ToSimdConstant<Bool32x4>(JSContext* cx, HandleValue v, jit::Si
template<typename Elem>
static Elem
TypedObjectMemory(HandleValue v, const JS::AutoAssertOnGC& nogc)
TypedObjectMemory(HandleValue v, const JS::AutoRequireNoGC& nogc)
{
TypedObject& obj = v.toObject().as<TypedObject>();
return reinterpret_cast<Elem>(obj.typedMem(nogc));

View File

@ -549,14 +549,14 @@ class TypedObject : public ShapedObject
int32_t offset() const;
int32_t length() const;
uint8_t* typedMem(const JS::AutoAssertOnGC&) const { return typedMem(); }
uint8_t* typedMem(const JS::AutoRequireNoGC&) const { return typedMem(); }
bool isAttached() const;
int32_t size() const {
return typeDescr().size();
}
uint8_t* typedMem(size_t offset, const JS::AutoAssertOnGC& nogc) const {
uint8_t* typedMem(size_t offset, const JS::AutoRequireNoGC& nogc) const {
// It seems a bit surprising that one might request an offset
// == size(), but it can happen when taking the "address of" a
// 0-sized value. (In other words, we maintain the invariant
@ -704,7 +704,7 @@ class InlineTypedObject : public TypedObject
return gc::GetGCObjectKindForBytes(nbytes + sizeof(TypedObject));
}
uint8_t* inlineTypedMem(const JS::AutoAssertOnGC&) const {
uint8_t* inlineTypedMem(const JS::AutoRequireNoGC&) const {
return inlineTypedMem();
}

View File

@ -203,7 +203,7 @@ GCRuntime::checkAllocatorState(JSContext* cx, AllocKind kind)
// Crash if we perform a GC action when it is not safe.
if (allowGC && !rt->mainThread.suppressGC)
JS::AutoAssertOnGC::VerifyIsSafeToGC(rt);
rt->gc.verifyIsSafeToGC();
// For testing out of memory conditions
if (js::oom::ShouldFailWithOOM()) {

View File

@ -24,6 +24,7 @@ namespace js {
class AutoLockGC;
class AutoLockHelperThreadState;
class SliceBudget;
class VerifyPreTracer;
namespace gc {
@ -721,13 +722,6 @@ class GCRuntime
--noNurseryAllocationCheck;
}
bool isInsideUnsafeRegion() { return inUnsafeRegion != 0; }
void enterUnsafeRegion() { ++inUnsafeRegion; }
void leaveUnsafeRegion() {
MOZ_ASSERT(inUnsafeRegion > 0);
--inUnsafeRegion;
}
bool isStrictProxyCheckingEnabled() { return disableStrictProxyCheckingCount == 0; }
void disableStrictProxyChecking() { ++disableStrictProxyCheckingCount; }
void enableStrictProxyChecking() {
@ -736,6 +730,18 @@ class GCRuntime
}
#endif // DEBUG
bool isInsideUnsafeRegion() { return inUnsafeRegion != 0; }
void enterUnsafeRegion() { ++inUnsafeRegion; }
void leaveUnsafeRegion() {
MOZ_ASSERT(inUnsafeRegion > 0);
--inUnsafeRegion;
}
void verifyIsSafeToGC() {
MOZ_DIAGNOSTIC_ASSERT(!isInsideUnsafeRegion(),
"[AutoAssertOnGC] possible GC in GC-unsafe region");
}
void setAlwaysPreserveCode() { alwaysPreserveCode = true; }
bool isIncrementalGCAllowed() const { return incrementalAllowed; }
@ -858,6 +864,19 @@ class GCRuntime
bool isVerifyPreBarriersEnabled() const { return false; }
#endif
// GC interrupt callbacks.
bool addInterruptCallback(JS::GCInterruptCallback callback);
void requestInterruptCallback();
bool checkInterruptCallback(JSContext* cx) {
if (interruptCallbackRequested) {
invokeInterruptCallback(cx);
return true;
}
return false;
}
void invokeInterruptCallback(JSContext* cx);
// Free certain LifoAlloc blocks when it is safe to do so.
void freeUnusedLifoBlocksAfterSweeping(LifoAlloc* lifo);
void freeAllLifoBlocksAfterSweeping(LifoAlloc* lifo);
@ -1070,6 +1089,13 @@ class GCRuntime
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> numArenasFreeCommitted;
VerifyPreTracer* verifyPreData;
// GC interrupt callbacks.
using GCInterruptCallbackVector = js::Vector<JS::GCInterruptCallback, 2, js::SystemAllocPolicy>;
GCInterruptCallbackVector interruptCallbacks;
mozilla::Atomic<bool, mozilla::Relaxed> interruptCallbackRequested;
SliceBudget* currentBudget;
private:
bool chunkAllocationSinceLastGC;
int64_t lastGCTime;
@ -1344,7 +1370,6 @@ class GCRuntime
/* Always preserve JIT code during GCs, for testing. */
bool alwaysPreserveCode;
#ifdef DEBUG
/*
* Some regions of code are hard for the static rooting hazard analysis to
* understand. In those cases, we trade the static analysis for a dynamic
@ -1353,6 +1378,7 @@ class GCRuntime
*/
int inUnsafeRegion;
#ifdef DEBUG
size_t noGCOrAllocationCheck;
size_t noNurseryAllocationCheck;

View File

@ -1545,13 +1545,15 @@ GCMarker::drainMarkStack(SliceBudget& budget)
auto acc = mozilla::MakeScopeExit([&] {strictCompartmentChecking = false;});
#endif
if (budget.isOverBudget())
JSContext* cx = runtime()->contextFromMainThread();
if (budget.isOverBudget(cx))
return false;
for (;;) {
while (!stack.isEmpty()) {
processMarkStackTop(budget);
if (budget.isOverBudget()) {
if (budget.isOverBudget(cx)) {
saveValueRanges();
return false;
}
@ -1626,6 +1628,8 @@ GCMarker::processMarkStackTop(SliceBudget& budget)
uintptr_t tag = addr & StackTagMask;
addr &= ~StackTagMask;
JSContext* cx = runtime()->contextFromMainThread();
// Dispatch
switch (tag) {
case ValueArrayTag: {
@ -1679,7 +1683,7 @@ GCMarker::processMarkStackTop(SliceBudget& budget)
MOZ_ASSERT(vp <= end);
while (vp != end) {
budget.step();
if (budget.isOverBudget()) {
if (budget.isOverBudget(cx)) {
pushValueArray(obj, vp, end);
return;
}
@ -1709,7 +1713,7 @@ GCMarker::processMarkStackTop(SliceBudget& budget)
AssertZoneIsMarking(obj);
budget.step();
if (budget.isOverBudget()) {
if (budget.isOverBudget(cx)) {
repush(obj);
return;
}
@ -2157,7 +2161,7 @@ GCMarker::markDelayedChildren(SliceBudget& budget)
markDelayedChildren(arena);
budget.step(150);
if (budget.isOverBudget())
if (budget.isOverBudget(runtime()->contextFromMainThread()))
return false;
} while (unmarkedArenaStackTop);
MOZ_ASSERT(!markLaterArenas);

View File

@ -188,6 +188,7 @@
#include "mozilla/MacroForEach.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Move.h"
#include "mozilla/ScopeExit.h"
#include <ctype.h>
#include <string.h>
@ -506,6 +507,8 @@ FinalizeTypedArenas(FreeOp* fop,
size_t thingSize = Arena::thingSize(thingKind);
size_t thingsPerArena = Arena::thingsPerArena(thingKind);
JSContext* cx = fop->onMainThread() ? fop->runtime()->contextFromMainThread() : nullptr;
while (Arena* arena = *src) {
*src = arena->next;
size_t nmarked = arena->finalize<T>(fop, thingKind, thingSize);
@ -519,7 +522,7 @@ FinalizeTypedArenas(FreeOp* fop,
fop->runtime()->gc.releaseArena(arena, maybeLock.ref());
budget.step(thingsPerArena);
if (budget.isOverBudget())
if (budget.isOverBudget(cx))
return false;
}
@ -808,6 +811,8 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
nextCellUniqueId_(LargestTaggedNullCellPointer + 1), // Ensure disjoint from null tagged pointers.
numArenasFreeCommitted(0),
verifyPreData(nullptr),
interruptCallbackRequested(false),
currentBudget(nullptr),
chunkAllocationSinceLastGC(false),
lastGCTime(PRMJ_Now()),
mode(JSGC_MODE_INCREMENTAL),
@ -864,8 +869,8 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
mallocBytesUntilGC(0),
mallocGCTriggered(false),
alwaysPreserveCode(false),
#ifdef DEBUG
inUnsafeRegion(0),
#ifdef DEBUG
noGCOrAllocationCheck(0),
noNurseryAllocationCheck(0),
arenasEmptyAtShutdown(true),
@ -2933,8 +2938,11 @@ SliceBudget::describe(char* buffer, size_t maxlen) const
}
bool
SliceBudget::checkOverBudget()
SliceBudget::checkOverBudget(JSContext* cx)
{
if (cx)
cx->gc.checkInterruptCallback(cx);
bool over = PRMJ_Now() >= deadline;
if (!over)
counter = CounterReset;
@ -5481,7 +5489,7 @@ GCRuntime::compactPhase(JS::gcreason::Reason reason, SliceBudget& sliceBudget,
updatePointersToRelocatedCells(zone, lock);
zone->setGCState(Zone::Finished);
zonesToMaybeCompact.removeFront();
if (sliceBudget.isOverBudget())
if (sliceBudget.isOverBudget(rt->contextFromMainThread()))
break;
}
@ -5887,7 +5895,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
* now exhasted.
*/
beginSweepPhase(destroyingRuntime, lock);
if (budget.isOverBudget())
if (budget.isOverBudget(rt->contextFromMainThread()))
break;
/*
@ -6133,7 +6141,7 @@ GCRuntime::gcCycle(bool nonincrementalByAPI, SliceBudget& budget, JS::gcreason::
MOZ_ASSERT(!rt->mainThread.suppressGC);
// Assert if this is a GC unsafe region.
JS::AutoAssertOnGC::VerifyIsSafeToGC(rt);
verifyIsSafeToGC();
{
gcstats::AutoPhase ap(stats, gcstats::PHASE_WAIT_BACKGROUND_THREAD);
@ -6294,6 +6302,11 @@ GCRuntime::collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::R
if (!checkIfGCAllowedInCurrentState(reason))
return;
currentBudget = &budget;
auto guard = mozilla::MakeScopeExit([&] {
currentBudget = nullptr;
});
AutoTraceLog logGC(TraceLoggerForMainThread(rt), TraceLogger_GC);
AutoStopVerifyingBarriers av(rt, IsShutdownGC(reason));
AutoEnqueuePendingParseTasksAfterGC aept(*this);
@ -6974,7 +6987,6 @@ JS::GetGCNumber()
}
#endif
#ifdef DEBUG
JS::AutoAssertOnGC::AutoAssertOnGC()
: gc(nullptr), gcNumber(0)
{
@ -7014,13 +7026,20 @@ JS::AutoAssertOnGC::~AutoAssertOnGC()
}
}
/* static */ void
JS::AutoAssertOnGC::VerifyIsSafeToGC(JSRuntime* rt)
JS::AutoAssertOnBarrier::AutoAssertOnBarrier(JSContext* cx)
: context(cx),
prev(cx->runtime()->allowGCBarriers())
{
if (rt->gc.isInsideUnsafeRegion())
MOZ_CRASH("[AutoAssertOnGC] possible GC in GC-unsafe region");
context->runtime()->allowGCBarriers_ = false;
}
JS::AutoAssertOnBarrier::~AutoAssertOnBarrier()
{
MOZ_ASSERT(!context->runtime()->allowGCBarriers_);
context->runtime()->allowGCBarriers_ = prev;
}
#ifdef DEBUG
JS::AutoAssertNoAlloc::AutoAssertNoAlloc(JSContext* cx)
: gc(nullptr)
{
@ -7662,3 +7681,41 @@ js::gc::Cell::dump() const
dump(stderr);
}
#endif
bool
JS::AddGCInterruptCallback(JSContext* cx, GCInterruptCallback callback)
{
return cx->runtime()->gc.addInterruptCallback(callback);
}
void
JS::RequestGCInterruptCallback(JSContext* cx)
{
cx->runtime()->gc.requestInterruptCallback();
}
bool
GCRuntime::addInterruptCallback(JS::GCInterruptCallback callback)
{
return interruptCallbacks.append(callback);
}
void
GCRuntime::requestInterruptCallback()
{
if (currentBudget) {
interruptCallbackRequested = true;
currentBudget->requestFullCheck();
}
}
void
GCRuntime::invokeInterruptCallback(JSContext* cx)
{
JS::AutoAssertOnGC nogc(cx);
JS::AutoAssertOnBarrier nobarrier(cx);
JS::AutoSuppressGCAnalysis suppress;
for (JS::GCInterruptCallback callback : interruptCallbacks) {
(*callback)(cx);
}
}

View File

@ -131,6 +131,7 @@ class StoreBuffer;
namespace JS {
class JS_PUBLIC_API(AutoEnterCycleCollection);
class JS_PUBLIC_API(AutoAssertOnBarrier);
struct PropertyDescriptor;
typedef void (*OffThreadCompileCallback)(void* token, void* callbackData);
@ -153,11 +154,17 @@ struct Runtime
friend class JS::AutoEnterCycleCollection;
JS::HeapState heapState_;
// In some cases, invoking GC barriers (incremental or otherwise) will break
// things. These barriers assert if this flag is set.
bool allowGCBarriers_;
friend class JS::AutoAssertOnBarrier;
js::gc::StoreBuffer* gcStoreBufferPtr_;
public:
Runtime()
: heapState_(JS::HeapState::Idle)
, allowGCBarriers_(true)
, gcStoreBufferPtr_(nullptr)
{}
@ -169,6 +176,8 @@ struct Runtime
return heapState_ == JS::HeapState::CycleCollecting;
}
bool allowGCBarriers() const { return allowGCBarriers_; }
js::gc::StoreBuffer* gcStoreBufferPtr() { return gcStoreBufferPtr_; }
static JS::shadow::Runtime* asShadowRuntime(JSRuntime* rt) {

View File

@ -1498,7 +1498,7 @@ ArrayBufferViewObject::notifyBufferDetached(JSContext* cx, void* newData)
}
uint8_t*
ArrayBufferViewObject::dataPointerUnshared(const JS::AutoAssertOnGC& nogc)
ArrayBufferViewObject::dataPointerUnshared(const JS::AutoRequireNoGC& nogc)
{
if (is<DataViewObject>())
return static_cast<uint8_t*>(as<DataViewObject>().dataPointer());

View File

@ -440,7 +440,7 @@ class ArrayBufferViewObject : public JSObject
// By construction we only need unshared variants here. See
// comments in ArrayBufferObject.cpp.
uint8_t* dataPointerUnshared(const JS::AutoAssertOnGC&);
uint8_t* dataPointerUnshared(const JS::AutoRequireNoGC&);
void setDataPointerUnshared(uint8_t* data);
static void trace(JSTracer* trc, JSObject* obj);

View File

@ -363,7 +363,7 @@ js::RunScript(JSContext* cx, RunState& state)
JS_CHECK_RECURSION(cx, return false);
// Since any script can conceivably GC, make sure it's safe to do so.
JS::AutoAssertOnGC::VerifyIsSafeToGC(cx->runtime());
cx->runtime()->gc.verifyIsSafeToGC();
if (!Debugger::checkNoExecute(cx, state.script()))
return false;

View File

@ -379,14 +379,10 @@ nsFileControlFrame::DnDListener::IsValidDropData(nsIDOMDataTransfer* aDOMDataTra
NS_ENSURE_TRUE(dataTransfer, false);
// We only support dropping files onto a file upload control
ErrorResult rv;
RefPtr<DOMStringList> types = dataTransfer->GetTypes(rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
return false;
}
nsTArray<nsString> types;
dataTransfer->GetTypes(types, *nsContentUtils::GetSystemPrincipal());
return types->Contains(NS_LITERAL_STRING("Files"));
return types.Contains(NS_LITERAL_STRING("Files"));
}
bool

View File

@ -1626,12 +1626,10 @@ CSSStyleSheet::DidDirty()
}
void
CSSStyleSheet::SubjectSubsumesInnerPrincipal(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
CSSStyleSheet::SubjectSubsumesInnerPrincipal(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(aSubjectPrincipal.isSome());
if (aSubjectPrincipal.value()->Subsumes(mInner->mPrincipal)) {
if (aSubjectPrincipal.Subsumes(mInner->mPrincipal)) {
return;
}
@ -1659,7 +1657,7 @@ CSSStyleSheet::SubjectSubsumesInnerPrincipal(const Maybe<nsIPrincipal*>& aSubjec
WillDirty();
mInner->mPrincipal = aSubjectPrincipal.value();
mInner->mPrincipal = &aSubjectPrincipal;
DidDirty();
}
@ -1782,13 +1780,13 @@ CSSStyleSheet::GetCssRules(nsIDOMCSSRuleList** aCssRules)
{
ErrorResult rv;
nsCOMPtr<nsIDOMCSSRuleList> rules =
GetCssRules(Some(nsContentUtils::SubjectPrincipal()), rv);
GetCssRules(*nsContentUtils::SubjectPrincipal(), rv);
rules.forget(aCssRules);
return rv.StealNSResult();
}
CSSRuleList*
CSSStyleSheet::GetCssRules(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
CSSStyleSheet::GetCssRules(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
// No doing this on incomplete sheets!
@ -1819,13 +1817,13 @@ CSSStyleSheet::InsertRule(const nsAString& aRule,
{
ErrorResult rv;
*aReturn =
InsertRule(aRule, aIndex, Some(nsContentUtils::SubjectPrincipal()), rv);
InsertRule(aRule, aIndex, *nsContentUtils::SubjectPrincipal(), rv);
return rv.StealNSResult();
}
uint32_t
CSSStyleSheet::InsertRule(const nsAString& aRule, uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
//-- Security check: Only scripts whose principal subsumes that of the
@ -1977,13 +1975,13 @@ NS_IMETHODIMP
CSSStyleSheet::DeleteRule(uint32_t aIndex)
{
ErrorResult rv;
DeleteRule(aIndex, Some(nsContentUtils::SubjectPrincipal()), rv);
DeleteRule(aIndex, *nsContentUtils::SubjectPrincipal(), rv);
return rv.StealNSResult();
}
void
CSSStyleSheet::DeleteRule(uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
// No doing this if the sheet is not complete!

View File

@ -246,14 +246,14 @@ public:
// called GetOwnerRule because that would be ambiguous with the ImportRule
// version.
nsIDOMCSSRule* GetDOMOwnerRule() const;
dom::CSSRuleList* GetCssRules(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
dom::CSSRuleList* GetCssRules(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
uint32_t InsertRule(const nsAString& aRule, uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
void DeleteRule(uint32_t aIndex,
const Maybe<nsIPrincipal*>& aSubjectPrincipal,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
// WebIDL miscellaneous bits
@ -291,7 +291,7 @@ protected:
// inner, error otherwise. This will also succeed if the subject has
// UniversalXPConnect or if access is allowed by CORS. In the latter case,
// it will set the principal of the inner to the subject principal.
void SubjectSubsumesInnerPrincipal(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
void SubjectSubsumesInnerPrincipal(nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv);
// Add the namespace mapping from this @namespace rule to our namespace map

View File

@ -38,13 +38,13 @@ SERVO_BINDING_FUNC(Servo_StyleSheet_HasRules, bool,
SERVO_BINDING_FUNC(Servo_StyleSet_Init, RawServoStyleSetOwned)
SERVO_BINDING_FUNC(Servo_StyleSet_Drop, void, RawServoStyleSetOwned set)
SERVO_BINDING_FUNC(Servo_StyleSet_AppendStyleSheet, void,
RawServoStyleSetBorrowedMut set, RawServoStyleSheetBorrowed sheet)
RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet)
SERVO_BINDING_FUNC(Servo_StyleSet_PrependStyleSheet, void,
RawServoStyleSetBorrowedMut set, RawServoStyleSheetBorrowed sheet)
RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet)
SERVO_BINDING_FUNC(Servo_StyleSet_RemoveStyleSheet, void,
RawServoStyleSetBorrowedMut set, RawServoStyleSheetBorrowed sheet)
RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet)
SERVO_BINDING_FUNC(Servo_StyleSet_InsertStyleSheetBefore, void,
RawServoStyleSetBorrowedMut set, RawServoStyleSheetBorrowed sheet,
RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet,
RawServoStyleSheetBorrowed reference)
// Animations API
@ -96,12 +96,12 @@ SERVO_BINDING_FUNC(Servo_ComputedValues_Get, ServoComputedValuesStrong,
SERVO_BINDING_FUNC(Servo_ComputedValues_GetForAnonymousBox,
ServoComputedValuesStrong,
ServoComputedValuesBorrowedOrNull parent_style_or_null,
nsIAtom* pseudoTag, RawServoStyleSetBorrowedMut set)
nsIAtom* pseudoTag, RawServoStyleSetBorrowed set)
SERVO_BINDING_FUNC(Servo_ComputedValues_GetForPseudoElement,
ServoComputedValuesStrong,
ServoComputedValuesBorrowed parent_style,
RawGeckoElementBorrowed match_element, nsIAtom* pseudo_tag,
RawServoStyleSetBorrowedMut set, bool is_probe)
RawServoStyleSetBorrowed set, bool is_probe)
SERVO_BINDING_FUNC(Servo_ComputedValues_Inherit, ServoComputedValuesStrong,
ServoComputedValuesBorrowedOrNull parent_style)
SERVO_BINDING_FUNC(Servo_ComputedValues_AddRef, void,
@ -121,7 +121,7 @@ SERVO_BINDING_FUNC(Servo_ComputeRestyleHint, nsRestyleHint,
// Restyle the given subtree.
SERVO_BINDING_FUNC(Servo_RestyleSubtree, void,
RawGeckoNodeBorrowed node, RawServoStyleSetBorrowedMut set)
RawGeckoNodeBorrowed node, RawServoStyleSetBorrowed set)
// Style-struct management.
#define STYLE_STRUCT(name, checkdata_cb) \

View File

@ -110,9 +110,18 @@ public:
void Clear();
// Must be copy-constructable and assignable
#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
#pragma pack(1)
#endif
struct nsEntry
{
nsHttpAtom header;
#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
char padding[4096 -
sizeof(nsTArrayHeader) -
sizeof(nsHttpAtom) -
sizeof(void*)];
#endif
nsCString value;
HeaderVariety variety = eVarietyUnknown;
@ -127,6 +136,9 @@ public:
return header == aOther.header && value == aOther.value;
}
};
#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
#pragma pack()
#endif
bool operator==(const nsHttpHeaderArray& aOther) const
{

View File

@ -16,6 +16,26 @@
namespace mozilla {
namespace net {
#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
void nsHttpRequestHead::DbgReentrantMonitorAutoEnter::Protect(bool aOn)
{
if (XRE_GetProcessType() == GeckoProcessType_Content &&
mInst.mHeaders.Count()) {
DWORD oldProtect;
LPVOID hdr = reinterpret_cast<PUINT8>(mInst.mHeaders.mHeaders.Elements()) -
sizeof(nsTArrayHeader);
if (aOn) {
VirtualProtect(hdr, 4096, PAGE_READONLY, &oldProtect);
} else {
VirtualProtect(hdr, 4096, PAGE_READWRITE, &oldProtect);
}
}
}
#define ReentrantMonitorAutoEnter DbgReentrantMonitorAutoEnter
#define mon(x) mon(*this)
#endif
nsHttpRequestHead::nsHttpRequestHead()
: mMethod(NS_LITERAL_CSTRING("GET"))
, mVersion(NS_HTTP_VERSION_1_1)
@ -29,6 +49,14 @@ nsHttpRequestHead::nsHttpRequestHead()
nsHttpRequestHead::~nsHttpRequestHead()
{
#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
if (XRE_GetProcessType() == GeckoProcessType_Content && mHeaders.Count()) {
DWORD oldProtect;
LPVOID hdr = reinterpret_cast<PUINT8>(mHeaders.mHeaders.Elements()) -
sizeof(nsTArrayHeader);
VirtualProtect(hdr, 4096, PAGE_READWRITE, &oldProtect);
}
#endif
MOZ_COUNT_DTOR(nsHttpRequestHead);
}
@ -365,5 +393,10 @@ nsHttpRequestHead::Flatten(nsACString &buf, bool pruneProxyHeaders)
mHeaders.Flatten(buf, pruneProxyHeaders, false);
}
#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
#undef ReentrantMonitorAutoEnter
#undef mon
#endif
} // namespace net
} // namespace mozilla

View File

@ -120,6 +120,28 @@ private:
// During VisitHeader we sould not allow cal to SetHeader.
bool mInVisitHeaders;
#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
class DbgReentrantMonitorAutoEnter : ReentrantMonitorAutoEnter
{
public:
explicit DbgReentrantMonitorAutoEnter(nsHttpRequestHead& aInst)
: ReentrantMonitorAutoEnter(aInst.mReentrantMonitor),
mInst(aInst)
{
Protect(false);
}
~DbgReentrantMonitorAutoEnter(void)
{
Protect(true);
}
private:
void Protect(bool aOn);
nsHttpRequestHead& mInst;
};
#endif
};
} // namespace net

View File

@ -515,7 +515,7 @@ ViewSourceChrome.prototype = {
// set the dropEffect to 'none'. This prevents the drop even if some
// other listener cancelled the event.
let types = event.dataTransfer.types;
if (types.contains("text/x-moz-text-internal") && !types.contains("text/plain")) {
if (types.includes("text/x-moz-text-internal") && !types.includes("text/plain")) {
event.dataTransfer.dropEffect = "none";
event.stopPropagation();
event.preventDefault();

View File

@ -655,7 +655,7 @@ function onToolbarDragOver(aEvent)
}
var documentId = gToolboxDocument.documentElement.id;
if (!aEvent.dataTransfer.types.contains("text/toolbarwrapper-id/" + documentId.toLowerCase()))
if (!aEvent.dataTransfer.types.includes("text/toolbarwrapper-id/" + documentId.toLowerCase()))
return;
var toolbar = aEvent.target;
@ -784,7 +784,7 @@ function onPaletteDragOver(aEvent)
return;
}
var documentId = gToolboxDocument.documentElement.id;
if (aEvent.dataTransfer.types.contains("text/toolbarwrapper-id/" + documentId.toLowerCase()))
if (aEvent.dataTransfer.types.includes("text/toolbarwrapper-id/" + documentId.toLowerCase()))
aEvent.preventDefault();
}

View File

@ -1445,7 +1445,7 @@
// set the dropEffect to 'none'. This prevents the drop even if some
// other listener cancelled the event.
var types = event.dataTransfer.types;
if (types.contains("text/x-moz-text-internal") && !types.contains("text/plain")) {
if (types.includes("text/x-moz-text-internal") && !types.includes("text/plain")) {
event.dataTransfer.dropEffect = "none";
event.stopPropagation();
event.preventDefault();

View File

@ -139,7 +139,7 @@
]]></handler>
<handler event="dragover"><![CDATA[
if (event.dataTransfer.types.contains("text/plain"))
if (event.dataTransfer.types.includes("text/plain"))
event.preventDefault();
]]></handler>

View File

@ -661,9 +661,9 @@ var gDownloadDNDObserver =
onDragOver: function (aEvent)
{
var types = aEvent.dataTransfer.types;
if (types.contains("text/uri-list") ||
types.contains("text/x-moz-url") ||
types.contains("text/plain"))
if (types.includes("text/uri-list") ||
types.includes("text/x-moz-url") ||
types.includes("text/plain"))
aEvent.preventDefault();
},

View File

@ -3820,9 +3820,9 @@ var gUpdatesView = {
var gDragDrop = {
onDragOver: function(aEvent) {
var types = aEvent.dataTransfer.types;
if (types.contains("text/uri-list") ||
types.contains("text/x-moz-url") ||
types.contains("application/x-moz-file"))
if (types.includes("text/uri-list") ||
types.includes("text/x-moz-url") ||
types.includes("application/x-moz-file"))
aEvent.preventDefault();
},

View File

@ -19,6 +19,7 @@
#include <X11/XKBlib.h>
#include "WidgetUtils.h"
#include "keysym2ucs.h"
#include "nsContentUtils.h"
#include "nsGtkUtils.h"
#include "nsIBidiKeyboard.h"
#include "nsServiceManagerUtils.h"
@ -41,7 +42,6 @@ KeymapWrapper* KeymapWrapper::sInstance = nullptr;
guint KeymapWrapper::sLastRepeatableHardwareKeyCode = 0;
KeymapWrapper::RepeatState KeymapWrapper::sRepeatState =
KeymapWrapper::NOT_PRESSED;
nsIBidiKeyboard* sBidiKeyboard = nullptr;
static const char* GetBoolName(bool aBool)
{
@ -170,6 +170,8 @@ KeymapWrapper::KeymapWrapper() :
g_object_ref(mGdkKeymap);
g_signal_connect(mGdkKeymap, "keys-changed",
(GCallback)OnKeysChanged, this);
g_signal_connect(mGdkKeymap, "direction-changed",
(GCallback)OnDirectionChanged, this);
if (GDK_IS_X11_DISPLAY(gdk_display_get_default()))
InitXKBExtension();
@ -442,8 +444,9 @@ KeymapWrapper::~KeymapWrapper()
gdk_window_remove_filter(nullptr, FilterEvents, this);
g_signal_handlers_disconnect_by_func(mGdkKeymap,
FuncToGpointer(OnKeysChanged), this);
g_signal_handlers_disconnect_by_func(mGdkKeymap,
FuncToGpointer(OnDirectionChanged), this);
g_object_unref(mGdkKeymap);
NS_IF_RELEASE(sBidiKeyboard);
MOZ_LOG(gKeymapWrapperLog, LogLevel::Info,
("%p Destructor", this));
}
@ -519,6 +522,17 @@ KeymapWrapper::FilterEvents(GdkXEvent* aXEvent,
return GDK_FILTER_CONTINUE;
}
static void
ResetBidiKeyboard()
{
// Reset the bidi keyboard settings for the new GdkKeymap
nsCOMPtr<nsIBidiKeyboard> bidiKeyboard = nsContentUtils::GetBidiKeyboard();
if (bidiKeyboard) {
bidiKeyboard->Reset();
}
WidgetUtils::SendBidiKeyboardInfoToContent();
}
/* static */ void
KeymapWrapper::OnKeysChanged(GdkKeymap *aGdkKeymap,
KeymapWrapper* aKeymapWrapper)
@ -533,14 +547,27 @@ KeymapWrapper::OnKeysChanged(GdkKeymap *aGdkKeymap,
// We cannot reintialize here becasue we don't have GdkWindow which is using
// the GdkKeymap. We'll reinitialize it when next GetInstance() is called.
sInstance->mInitialized = false;
ResetBidiKeyboard();
}
// Reset the bidi keyboard settings for the new GdkKeymap
if (!sBidiKeyboard) {
CallGetService("@mozilla.org/widget/bidikeyboard;1", &sBidiKeyboard);
}
if (sBidiKeyboard) {
sBidiKeyboard->Reset();
}
// static
void
KeymapWrapper::OnDirectionChanged(GdkKeymap *aGdkKeymap,
KeymapWrapper* aKeymapWrapper)
{
// XXX
// A lot of diretion-changed signal might be fired on switching bidi
// keyboard when using both ibus (with arabic layout) and fcitx (with IME).
// See https://github.com/fcitx/fcitx/issues/257
//
// Also, when using ibus, switching to IM might not cause this signal.
// See https://github.com/ibus/ibus/issues/1848
MOZ_LOG(gKeymapWrapperLog, LogLevel::Info,
("OnDirectionChanged, aGdkKeymap=%p, aKeymapWrapper=%p",
aGdkKeymap, aKeymapWrapper));
ResetBidiKeyboard();
}
/* static */ guint

View File

@ -257,6 +257,8 @@ protected:
* Signal handlers.
*/
static void OnKeysChanged(GdkKeymap* aKeymap, KeymapWrapper* aKeymapWrapper);
static void OnDirectionChanged(GdkKeymap *aGdkKeymap,
KeymapWrapper* aKeymapWrapper);
/**
* GetCharCodeFor() Computes what character is inputted by the key event