tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CanvasUtils.h (6678B)


      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/. */
      5 
      6 #ifndef _CANVASUTILS_H_
      7 #define _CANVASUTILS_H_
      8 
      9 #include "CanvasRenderingContextHelper.h"
     10 #include "js/Array.h"               // JS::GetArrayLength
     11 #include "js/PropertyAndElement.h"  // JS_GetElement
     12 #include "jsapi.h"
     13 #include "mozilla/CheckedInt.h"
     14 #include "mozilla/dom/ToJSValue.h"
     15 
     16 class nsIPrincipal;
     17 
     18 namespace mozilla {
     19 
     20 namespace dom {
     21 class Document;
     22 class HTMLCanvasElement;
     23 class OffscreenCanvas;
     24 }  // namespace dom
     25 
     26 namespace CanvasUtils {
     27 
     28 bool GetCanvasContextType(const nsAString& str,
     29                          dom::CanvasContextType* const out_type);
     30 
     31 // Check that the rectangle [x,y,w,h] is a subrectangle of
     32 // [0,0,realWidth,realHeight]
     33 
     34 inline bool CheckSaneSubrectSize(int32_t x, int32_t y, int32_t w, int32_t h,
     35                                 int32_t realWidth, int32_t realHeight) {
     36  CheckedInt32 checked_xmost = CheckedInt32(x) + w;
     37  CheckedInt32 checked_ymost = CheckedInt32(y) + h;
     38 
     39  return w >= 0 && h >= 0 && x >= 0 && y >= 0 && checked_xmost.isValid() &&
     40         checked_xmost.value() <= realWidth && checked_ymost.isValid() &&
     41         checked_ymost.value() <= realHeight;
     42 }
     43 
     44 // Flag aCanvasElement as write-only if drawing an image with aPrincipal
     45 // onto it would make it such.
     46 
     47 void DoDrawImageSecurityCheck(dom::HTMLCanvasElement* aCanvasElement,
     48                              nsIPrincipal* aPrincipal, bool forceWriteOnly,
     49                              bool CORSUsed);
     50 
     51 void DoDrawImageSecurityCheck(dom::OffscreenCanvas* aOffscreenCanvas,
     52                              nsIPrincipal* aPrincipal, bool forceWriteOnly,
     53                              bool CORSUsed);
     54 
     55 // Check if the context is chrome or has the permission to drawWindow
     56 bool HasDrawWindowPrivilege(JSContext* aCx, JSObject* aObj);
     57 
     58 // Check if the context has permission to use OffscreenCanvas.
     59 bool IsOffscreenCanvasEnabled(JSContext* aCx, JSObject* aObj);
     60 
     61 // Check if the principal has "canvas" permission.
     62 uint32_t GetCanvasExtractDataPermission(nsIPrincipal* aPrincipal);
     63 
     64 // Check site-specific permission and display prompt if appropriate.
     65 bool IsImageExtractionAllowed(dom::Document* aDocument, JSContext* aCx,
     66                              nsIPrincipal* aPrincipal);
     67 
     68 bool IsImageExtractionAllowed(dom::OffscreenCanvas* aOffscreenCanvas,
     69                              JSContext* aCx, nsIPrincipal* aPrincipal);
     70 
     71 uint32_t GetCanvasExtractDataPermission(nsIPrincipal* aPrincipal);
     72 
     73 enum class ImageExtraction {
     74  Unrestricted,
     75  Placeholder,
     76  Randomize,
     77  EfficientRandomize,
     78 };
     79 
     80 // Returns whether the result of an image extraction should be replaced
     81 // by a placeholder or randomized.
     82 ImageExtraction ImageExtractionResult(dom::HTMLCanvasElement* aCanvasElement,
     83                                      JSContext* aCx, nsIPrincipal* aPrincipal);
     84 ImageExtraction ImageExtractionResult(dom::OffscreenCanvas* aOffscreenCanvas,
     85                                      JSContext* aCx, nsIPrincipal* aPrincipal);
     86 
     87 // Make a double out of |v|, treating undefined values as 0.0 (for
     88 // the sake of sparse arrays).  Return true iff coercion
     89 // succeeded.
     90 bool CoerceDouble(const JS::Value& v, double* d);
     91 
     92 /* Float validation stuff */
     93 #define VALIDATE(_f) \
     94  if (!std::isfinite(_f)) return false
     95 
     96 inline bool FloatValidate(double f1) {
     97  VALIDATE(f1);
     98  return true;
     99 }
    100 
    101 inline bool FloatValidate(double f1, double f2) {
    102  VALIDATE(f1);
    103  VALIDATE(f2);
    104  return true;
    105 }
    106 
    107 inline bool FloatValidate(double f1, double f2, double f3) {
    108  VALIDATE(f1);
    109  VALIDATE(f2);
    110  VALIDATE(f3);
    111  return true;
    112 }
    113 
    114 inline bool FloatValidate(double f1, double f2, double f3, double f4) {
    115  VALIDATE(f1);
    116  VALIDATE(f2);
    117  VALIDATE(f3);
    118  VALIDATE(f4);
    119  return true;
    120 }
    121 
    122 inline bool FloatValidate(double f1, double f2, double f3, double f4,
    123                          double f5) {
    124  VALIDATE(f1);
    125  VALIDATE(f2);
    126  VALIDATE(f3);
    127  VALIDATE(f4);
    128  VALIDATE(f5);
    129  return true;
    130 }
    131 
    132 inline bool FloatValidate(double f1, double f2, double f3, double f4, double f5,
    133                          double f6) {
    134  VALIDATE(f1);
    135  VALIDATE(f2);
    136  VALIDATE(f3);
    137  VALIDATE(f4);
    138  VALIDATE(f5);
    139  VALIDATE(f6);
    140  return true;
    141 }
    142 
    143 #undef VALIDATE
    144 
    145 template <typename T>
    146 nsresult JSValToDashArray(JSContext* cx, const JS::Value& patternArray,
    147                          nsTArray<T>& dashes) {
    148  // The cap is pretty arbitrary.  16k should be enough for
    149  // anybody...
    150  static const uint32_t MAX_NUM_DASHES = 1 << 14;
    151 
    152  if (!patternArray.isPrimitive()) {
    153    JS::Rooted<JSObject*> obj(cx, patternArray.toObjectOrNull());
    154    uint32_t length;
    155    if (!JS::GetArrayLength(cx, obj, &length)) {
    156      // Not an array-like thing
    157      return NS_ERROR_INVALID_ARG;
    158    } else if (length > MAX_NUM_DASHES) {
    159      // Too many dashes in the pattern
    160      return NS_ERROR_ILLEGAL_VALUE;
    161    }
    162 
    163    bool haveNonzeroElement = false;
    164    for (uint32_t i = 0; i < length; ++i) {
    165      JS::Rooted<JS::Value> elt(cx);
    166      double d;
    167      if (!JS_GetElement(cx, obj, i, &elt)) {
    168        return NS_ERROR_FAILURE;
    169      }
    170      if (!(CoerceDouble(elt, &d) && FloatValidate(d) && d >= 0.0)) {
    171        // Pattern elements must be finite "numbers" >= 0.
    172        return NS_ERROR_INVALID_ARG;
    173      } else if (d > 0.0) {
    174        haveNonzeroElement = true;
    175      }
    176      if (!dashes.AppendElement(d, mozilla::fallible)) {
    177        return NS_ERROR_OUT_OF_MEMORY;
    178      }
    179    }
    180 
    181    if (dashes.Length() > 0 && !haveNonzeroElement) {
    182      // An all-zero pattern makes no sense.
    183      return NS_ERROR_ILLEGAL_VALUE;
    184    }
    185  } else if (!(patternArray.isUndefined() || patternArray.isNull())) {
    186    // undefined and null mean "reset to no dash".  Any other
    187    // random garbage is a type error.
    188    return NS_ERROR_INVALID_ARG;
    189  }
    190 
    191  return NS_OK;
    192 }
    193 
    194 template <typename T>
    195 void DashArrayToJSVal(nsTArray<T>& dashes, JSContext* cx,
    196                      JS::MutableHandle<JS::Value> retval,
    197                      mozilla::ErrorResult& rv) {
    198  if (dashes.IsEmpty()) {
    199    retval.setNull();
    200    return;
    201  }
    202  JS::Rooted<JS::Value> val(cx);
    203  if (!mozilla::dom::ToJSValue(cx, dashes, retval)) {
    204    rv.Throw(NS_ERROR_OUT_OF_MEMORY);
    205  }
    206 }
    207 
    208 // returns true if write-only mode must used for this principal based on
    209 // the incumbent global.
    210 bool CheckWriteOnlySecurity(bool aCORSUsed, nsIPrincipal* aPrincipal,
    211                            bool aHadCrossOriginRedirects);
    212 
    213 }  // namespace CanvasUtils
    214 }  // namespace mozilla
    215 
    216 #endif /* _CANVASUTILS_H_ */