1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef _CANVASUTILS_H_
7 #define _CANVASUTILS_H_
9 #include "CanvasRenderingContextHelper.h"
10 #include "mozilla/CheckedInt.h"
11 #include "mozilla/dom/ToJSValue.h"
13 #include "js/Array.h" // JS::GetArrayLength
14 #include "js/PropertyAndElement.h" // JS_GetElement
15 #include "mozilla/FloatingPoint.h"
23 class HTMLCanvasElement
;
24 class OffscreenCanvas
;
27 namespace CanvasUtils
{
29 bool GetCanvasContextType(const nsAString
& str
,
30 dom::CanvasContextType
* const out_type
);
32 // Check that the rectangle [x,y,w,h] is a subrectangle of
33 // [0,0,realWidth,realHeight]
35 inline bool CheckSaneSubrectSize(int32_t x
, int32_t y
, int32_t w
, int32_t h
,
36 int32_t realWidth
, int32_t realHeight
) {
37 CheckedInt32 checked_xmost
= CheckedInt32(x
) + w
;
38 CheckedInt32 checked_ymost
= CheckedInt32(y
) + h
;
40 return w
>= 0 && h
>= 0 && x
>= 0 && y
>= 0 && checked_xmost
.isValid() &&
41 checked_xmost
.value() <= realWidth
&& checked_ymost
.isValid() &&
42 checked_ymost
.value() <= realHeight
;
45 // Flag aCanvasElement as write-only if drawing an image with aPrincipal
46 // onto it would make it such.
48 void DoDrawImageSecurityCheck(dom::HTMLCanvasElement
* aCanvasElement
,
49 nsIPrincipal
* aPrincipal
, bool forceWriteOnly
,
52 void DoDrawImageSecurityCheck(dom::OffscreenCanvas
* aOffscreenCanvas
,
53 nsIPrincipal
* aPrincipal
, bool forceWriteOnly
,
56 // Check if the context is chrome or has the permission to drawWindow
57 bool HasDrawWindowPrivilege(JSContext
* aCx
, JSObject
* aObj
);
59 // Check if the context has permission to use OffscreenCanvas.
60 bool IsOffscreenCanvasEnabled(JSContext
* aCx
, JSObject
* aObj
);
62 // Check site-specific permission and display prompt if appropriate.
63 bool IsImageExtractionAllowed(dom::Document
* aDocument
, JSContext
* aCx
,
64 nsIPrincipal
& aPrincipal
);
66 enum class ImageExtraction
{
72 // Returns whether the result of an image extraction should be replaced
73 // by a placeholder or randomized.
74 ImageExtraction
ImageExtractionResult(dom::HTMLCanvasElement
* aCanvasElement
,
75 JSContext
* aCx
, nsIPrincipal
& aPrincipal
);
76 ImageExtraction
ImageExtractionResult(dom::OffscreenCanvas
* aOffscreenCanvas
,
77 JSContext
* aCx
, nsIPrincipal
& aPrincipal
);
79 // Make a double out of |v|, treating undefined values as 0.0 (for
80 // the sake of sparse arrays). Return true iff coercion
82 bool CoerceDouble(const JS::Value
& v
, double* d
);
84 /* Float validation stuff */
85 #define VALIDATE(_f) \
86 if (!std::isfinite(_f)) return false
88 inline bool FloatValidate(double f1
) {
93 inline bool FloatValidate(double f1
, double f2
) {
99 inline bool FloatValidate(double f1
, double f2
, double f3
) {
106 inline bool FloatValidate(double f1
, double f2
, double f3
, double f4
) {
114 inline bool FloatValidate(double f1
, double f2
, double f3
, double f4
,
124 inline bool FloatValidate(double f1
, double f2
, double f3
, double f4
, double f5
,
137 template <typename T
>
138 nsresult
JSValToDashArray(JSContext
* cx
, const JS::Value
& patternArray
,
139 nsTArray
<T
>& dashes
) {
140 // The cap is pretty arbitrary. 16k should be enough for
142 static const uint32_t MAX_NUM_DASHES
= 1 << 14;
144 if (!patternArray
.isPrimitive()) {
145 JS::Rooted
<JSObject
*> obj(cx
, patternArray
.toObjectOrNull());
147 if (!JS::GetArrayLength(cx
, obj
, &length
)) {
148 // Not an array-like thing
149 return NS_ERROR_INVALID_ARG
;
150 } else if (length
> MAX_NUM_DASHES
) {
151 // Too many dashes in the pattern
152 return NS_ERROR_ILLEGAL_VALUE
;
155 bool haveNonzeroElement
= false;
156 for (uint32_t i
= 0; i
< length
; ++i
) {
157 JS::Rooted
<JS::Value
> elt(cx
);
159 if (!JS_GetElement(cx
, obj
, i
, &elt
)) {
160 return NS_ERROR_FAILURE
;
162 if (!(CoerceDouble(elt
, &d
) && FloatValidate(d
) && d
>= 0.0)) {
163 // Pattern elements must be finite "numbers" >= 0.
164 return NS_ERROR_INVALID_ARG
;
165 } else if (d
> 0.0) {
166 haveNonzeroElement
= true;
168 if (!dashes
.AppendElement(d
, mozilla::fallible
)) {
169 return NS_ERROR_OUT_OF_MEMORY
;
173 if (dashes
.Length() > 0 && !haveNonzeroElement
) {
174 // An all-zero pattern makes no sense.
175 return NS_ERROR_ILLEGAL_VALUE
;
177 } else if (!(patternArray
.isUndefined() || patternArray
.isNull())) {
178 // undefined and null mean "reset to no dash". Any other
179 // random garbage is a type error.
180 return NS_ERROR_INVALID_ARG
;
186 template <typename T
>
187 void DashArrayToJSVal(nsTArray
<T
>& dashes
, JSContext
* cx
,
188 JS::MutableHandle
<JS::Value
> retval
,
189 mozilla::ErrorResult
& rv
) {
190 if (dashes
.IsEmpty()) {
194 JS::Rooted
<JS::Value
> val(cx
);
195 if (!mozilla::dom::ToJSValue(cx
, dashes
, retval
)) {
196 rv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
200 // returns true if write-only mode must used for this principal based on
201 // the incumbent global.
202 bool CheckWriteOnlySecurity(bool aCORSUsed
, nsIPrincipal
* aPrincipal
,
203 bool aHadCrossOriginRedirects
);
205 } // namespace CanvasUtils
206 } // namespace mozilla
208 #endif /* _CANVASUTILS_H_ */