summaryrefslogtreecommitdiffstats
path: root/dom/html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/html')
-rw-r--r--dom/html/HTMLCanvasElement.cpp43
-rw-r--r--dom/html/HTMLCanvasElement.h17
2 files changed, 50 insertions, 10 deletions
diff --git a/dom/html/HTMLCanvasElement.cpp b/dom/html/HTMLCanvasElement.cpp
index 0417a30..3a4d67a 100644
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -586,9 +586,8 @@ bool HTMLCanvasElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
void HTMLCanvasElement::ToDataURL(JSContext* aCx, const nsAString& aType,
JS::Handle<JS::Value> aParams,
nsAString& aDataURL, ErrorResult& aRv) {
- // do a trust check if this is a write-only canvas
- if (mWriteOnly && !nsContentUtils::CallerHasPermission(
- aCx, nsGkAtoms::all_urlsPermission)) {
+ // mWriteOnly check is redundant, but optimizes for the common case.
+ if (mWriteOnly && !CallerCanRead(aCx)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
@@ -761,9 +760,8 @@ void HTMLCanvasElement::ToBlob(JSContext* aCx, BlobCallback& aCallback,
const nsAString& aType,
JS::Handle<JS::Value> aParams,
ErrorResult& aRv) {
- // do a trust check if this is a write-only canvas
- if (mWriteOnly && !nsContentUtils::CallerHasPermission(
- aCx, nsGkAtoms::all_urlsPermission)) {
+ // mWriteOnly check is redundant, but optimizes for the common case.
+ if (mWriteOnly && !CallerCanRead(aCx)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
@@ -939,9 +937,38 @@ already_AddRefed<nsISupports> HTMLCanvasElement::MozGetIPCContext(
nsIntSize HTMLCanvasElement::GetSize() { return GetWidthHeight(); }
-bool HTMLCanvasElement::IsWriteOnly() { return mWriteOnly; }
+bool HTMLCanvasElement::IsWriteOnly() const { return mWriteOnly; }
+
+void HTMLCanvasElement::SetWriteOnly() {
+ mExpandedReader = nullptr;
+ mWriteOnly = true;
+}
+
+void
+HTMLCanvasElement::SetWriteOnly(nsIPrincipal* aExpandedReader)
+{
+ mExpandedReader = aExpandedReader;
+ mWriteOnly = true;
+}
+
+bool
+HTMLCanvasElement::CallerCanRead(JSContext* aCx)
+{
+ if (!mWriteOnly) {
+ return true;
+ }
-void HTMLCanvasElement::SetWriteOnly() { mWriteOnly = true; }
+ nsIPrincipal* prin = nsContentUtils::SubjectPrincipal(aCx);
+
+ // If mExpandedReader is set, this canvas was tainted only by
+ // mExpandedReader's resources. So allow reading if the subject
+ // principal subsumes mExpandedReader.
+ if (mExpandedReader && prin->Subsumes(mExpandedReader)) {
+ return true;
+ }
+
+ return nsContentUtils::PrincipalHasPermission(prin, nsGkAtoms::all_urlsPermission);
+}
void HTMLCanvasElement::InvalidateCanvasContent(const gfx::Rect* damageRect) {
// We don't need to flush anything here; if there's no frame or if
diff --git a/dom/html/HTMLCanvasElement.h b/dom/html/HTMLCanvasElement.h
index 76c1cbf..99b9be8 100644
--- a/dom/html/HTMLCanvasElement.h
+++ b/dom/html/HTMLCanvasElement.h
@@ -201,7 +201,7 @@ class HTMLCanvasElement final : public nsGenericHTMLElement,
/**
* Determine whether the canvas is write-only.
*/
- bool IsWriteOnly();
+ bool IsWriteOnly() const;
/**
* Force the canvas to be write-only.
@@ -209,6 +209,12 @@ class HTMLCanvasElement final : public nsGenericHTMLElement,
void SetWriteOnly();
/**
+ * Force the canvas to be write-only, except for readers from
+ * a specific extension's content script expanded principal.
+ */
+ void SetWriteOnly(nsIPrincipal* aExpandedReader);
+
+ /**
* Notify that some canvas content has changed and the window may
* need to be updated. aDamageRect is in canvas coordinates.
*/
@@ -369,7 +375,14 @@ class HTMLCanvasElement final : public nsGenericHTMLElement,
// We also transitively set it when script paints a canvas which
// is itself write-only.
bool mWriteOnly;
-
+
+ // When this canvas is (only) tainted by an image from an extension
+ // content script, allow reads from the same extension afterwards.
+ RefPtr<nsIPrincipal> mExpandedReader;
+
+ // Determines if the caller should be able to read the content.
+ bool CallerCanRead(JSContext* aCx);
+
bool IsPrintCallbackDone();
void HandlePrintCallback(nsPresContext::nsPresContextType aType);