tor-browser

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

HTMLCanvasElement.h (15246B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 #ifndef mozilla_dom_HTMLCanvasElement_h
      7 #define mozilla_dom_HTMLCanvasElement_h
      8 
      9 #include "LayoutConstants.h"
     10 #include "mozilla/Attributes.h"
     11 #include "mozilla/StateWatching.h"
     12 #include "mozilla/WeakPtr.h"
     13 #include "mozilla/dom/CanvasRenderingContextHelper.h"
     14 #include "mozilla/gfx/Rect.h"
     15 #include "mozilla/layers/LayersTypes.h"
     16 #include "nsError.h"
     17 #include "nsGenericHTMLElement.h"
     18 #include "nsGkAtoms.h"
     19 #include "nsIObserver.h"
     20 #include "nsSize.h"
     21 
     22 class nsICanvasRenderingContextInternal;
     23 class nsIInputStream;
     24 class nsITimerCallback;
     25 enum class gfxAlphaType;
     26 enum class FrameCaptureState : uint8_t;
     27 
     28 namespace mozilla {
     29 
     30 class nsDisplayListBuilder;
     31 class ClientWebGLContext;
     32 
     33 namespace layers {
     34 class CanvasRenderer;
     35 class Image;
     36 class ImageContainer;
     37 class Layer;
     38 class LayerManager;
     39 class OOPCanvasRenderer;
     40 class SharedSurfaceTextureClient;
     41 class WebRenderCanvasData;
     42 }  // namespace layers
     43 namespace gfx {
     44 class DrawTarget;
     45 class SourceSurface;
     46 class VRLayerChild;
     47 }  // namespace gfx
     48 namespace webgpu {
     49 class CanvasContext;
     50 }  // namespace webgpu
     51 
     52 namespace dom {
     53 class BlobCallback;
     54 class CanvasCaptureMediaStream;
     55 class File;
     56 class HTMLCanvasPrintState;
     57 class OffscreenCanvas;
     58 class OffscreenCanvasDisplayHelper;
     59 class PrintCallback;
     60 class PWebGLChild;
     61 class RequestedFrameRefreshObserver;
     62 
     63 // Listen visibilitychange and memory-pressure event and inform
     64 // context when event is fired.
     65 class HTMLCanvasElementObserver final : public nsIObserver {
     66 public:
     67  NS_DECL_ISUPPORTS
     68  NS_DECL_NSIOBSERVER
     69 
     70  explicit HTMLCanvasElementObserver(HTMLCanvasElement* aElement);
     71  void Destroy();
     72 
     73  void RegisterObserverEvents();
     74  void UnregisterObserverEvents();
     75 
     76 private:
     77  ~HTMLCanvasElementObserver();
     78 
     79  HTMLCanvasElement* mElement;
     80 };
     81 
     82 /*
     83 * FrameCaptureListener is used by captureStream() as a way of getting video
     84 * frames from the canvas. On a refresh driver tick after something has been
     85 * drawn to the canvas since the last such tick, all registered
     86 * FrameCaptureListeners that report true for FrameCaptureRequested() will be
     87 * given a copy of the just-painted canvas.
     88 * All FrameCaptureListeners get the same copy.
     89 */
     90 class FrameCaptureListener : public SupportsWeakPtr {
     91 public:
     92  FrameCaptureListener() = default;
     93 
     94  /*
     95   * Indicates to the canvas whether or not this listener has requested a frame.
     96   */
     97  virtual bool FrameCaptureRequested(const TimeStamp& aTime) const = 0;
     98 
     99  /*
    100   * Interface through which new video frames will be provided while
    101   * `mFrameCaptureRequested` is `true`.
    102   */
    103  virtual void NewFrame(already_AddRefed<layers::Image> aImage,
    104                        const TimeStamp& aTime) = 0;
    105 
    106 protected:
    107  virtual ~FrameCaptureListener() = default;
    108 };
    109 
    110 class HTMLCanvasElement final : public nsGenericHTMLElement,
    111                                public CanvasRenderingContextHelper,
    112                                public SupportsWeakPtr {
    113  typedef layers::CanvasRenderer CanvasRenderer;
    114  typedef layers::LayerManager LayerManager;
    115  typedef layers::WebRenderCanvasData WebRenderCanvasData;
    116 
    117 public:
    118  explicit HTMLCanvasElement(
    119      already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
    120 
    121  NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLCanvasElement, canvas)
    122 
    123  // nsISupports
    124  NS_DECL_ISUPPORTS_INHERITED
    125 
    126  // CC
    127  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLCanvasElement,
    128                                           nsGenericHTMLElement)
    129 
    130  // WebIDL
    131  uint32_t Height() {
    132    return GetUnsignedIntAttr(nsGkAtoms::height,
    133                              kFallbackIntrinsicHeightInPixels);
    134  }
    135  uint32_t Width() {
    136    return GetUnsignedIntAttr(nsGkAtoms::width,
    137                              kFallbackIntrinsicWidthInPixels);
    138  }
    139  void SetHeight(uint32_t aHeight, ErrorResult& aRv);
    140  void SetWidth(uint32_t aWidth, ErrorResult& aRv);
    141 
    142  already_AddRefed<nsISupports> GetContext(
    143      JSContext* aCx, const nsAString& aContextId,
    144      JS::Handle<JS::Value> aContextOptions, ErrorResult& aRv);
    145 
    146  void ToDataURL(JSContext* aCx, const nsAString& aType,
    147                 JS::Handle<JS::Value> aParams, nsAString& aDataURL,
    148                 nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
    149 
    150  void ToBlob(JSContext* aCx, BlobCallback& aCallback, const nsAString& aType,
    151              JS::Handle<JS::Value> aParams, nsIPrincipal& aSubjectPrincipal,
    152              ErrorResult& aRv);
    153 
    154  OffscreenCanvas* TransferControlToOffscreen(ErrorResult& aRv);
    155 
    156  bool MozOpaque() const { return GetBoolAttr(nsGkAtoms::moz_opaque); }
    157  void SetMozOpaque(bool aValue, ErrorResult& aRv) {
    158    if (mOffscreenCanvas) {
    159      aRv.Throw(NS_ERROR_FAILURE);
    160      return;
    161    }
    162 
    163    SetHTMLBoolAttr(nsGkAtoms::moz_opaque, aValue, aRv);
    164  }
    165  PrintCallback* GetMozPrintCallback() const;
    166  void SetMozPrintCallback(PrintCallback* aCallback);
    167 
    168  already_AddRefed<CanvasCaptureMediaStream> CaptureStream(
    169      const Optional<double>& aFrameRate, nsIPrincipal& aSubjectPrincipal,
    170      ErrorResult& aRv);
    171 
    172  /**
    173   * Get the size in pixels of this canvas element
    174   */
    175  CSSIntSize GetSize();
    176 
    177  /**
    178   * Set the size in pixels of this canvas element.
    179   */
    180  void SetSize(const nsIntSize& aSize, ErrorResult& aRv);
    181 
    182  /**
    183   * Determine whether the canvas is write-only.
    184   */
    185  bool IsWriteOnly() const;
    186 
    187  /**
    188   * Force the canvas to be write-only, except for readers from
    189   * a specific extension's content script expanded principal, if
    190   * available.
    191   */
    192  void SetWriteOnly(nsIPrincipal* aExpandedReader = nullptr);
    193 
    194  /**
    195   * Notify the placeholder offscreen canvas of an updated size.
    196   */
    197  void InvalidateCanvasPlaceholder(uint32_t aWidth, uint32_t aHeight);
    198 
    199  /**
    200   * Notify that some canvas content has changed and the window may
    201   * need to be updated. aDamageRect is in canvas coordinates.
    202   */
    203  void InvalidateCanvasContent(const mozilla::gfx::Rect* aDamageRect);
    204  /*
    205   * Notify that we need to repaint the entire canvas, including updating of
    206   * the layer tree.
    207   */
    208  void InvalidateCanvas();
    209 
    210  nsICanvasRenderingContextInternal* GetCurrentContext() {
    211    return mCurrentContext;
    212  }
    213 
    214  /*
    215   * Returns true if the canvas context content is guaranteed to be opaque
    216   * across its entire area.
    217   */
    218  bool GetIsOpaque();
    219  virtual bool GetOpaqueAttr() override;
    220 
    221  /**
    222   * Retrieve a snapshot of the internal surface, returning the alpha type if
    223   * requested. An optional target may be supplied for which the snapshot will
    224   * be optimized for, if possible.
    225   */
    226  virtual already_AddRefed<gfx::SourceSurface> GetSurfaceSnapshot(
    227      gfxAlphaType* aOutAlphaType = nullptr,
    228      gfx::DrawTarget* aTarget = nullptr);
    229 
    230  /*
    231   * Register a FrameCaptureListener with this canvas.
    232   * The canvas hooks into the RefreshDriver while there are
    233   * FrameCaptureListeners registered.
    234   * The registered FrameCaptureListeners are stored as WeakPtrs, thus it's the
    235   * caller's responsibility to keep them alive. Once a registered
    236   * FrameCaptureListener is destroyed it will be automatically deregistered.
    237   */
    238  nsresult RegisterFrameCaptureListener(FrameCaptureListener* aListener,
    239                                        bool aReturnPlaceholderData);
    240 
    241  /*
    242   * Returns true when there is at least one registered FrameCaptureListener
    243   * that has requested a frame capture.
    244   */
    245  bool IsFrameCaptureRequested(const TimeStamp& aTime) const;
    246 
    247  /*
    248   * Processes destroyed FrameCaptureListeners and removes them if necessary.
    249   * Should there be none left, the FrameRefreshObserver will be unregistered.
    250   */
    251  void ProcessDestroyedFrameListeners();
    252 
    253  /*
    254   * Called by the RefreshDriver hook when a frame has been captured.
    255   * Makes a copy of the provided surface and hands it to all
    256   * FrameCaptureListeners having requested frame capture.
    257   */
    258  void SetFrameCapture(already_AddRefed<gfx::SourceSurface> aSurface,
    259                       const TimeStamp& aTime);
    260 
    261  virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
    262                              const nsAString& aValue,
    263                              nsIPrincipal* aMaybeScriptedPrincipal,
    264                              nsAttrValue& aResult) override;
    265  NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
    266  nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
    267                                      AttrModType aModType) const override;
    268  nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
    269 
    270  virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
    271  nsresult CopyInnerTo(HTMLCanvasElement* aDest);
    272 
    273  static void MapAttributesIntoRule(MappedDeclarationsBuilder&);
    274 
    275  /*
    276   * Helpers called by various users of Canvas
    277   */
    278 
    279  already_AddRefed<layers::Image> GetAsImage();
    280  bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
    281                                 WebRenderCanvasData* aCanvasData);
    282  bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
    283                                CanvasRenderer* aRenderer);
    284 
    285  // Call this whenever we need future changes to the canvas
    286  // to trigger fresh invalidation requests. This needs to be called
    287  // whenever we render the canvas contents to the screen, or whenever we
    288  // take a snapshot of the canvas that needs to be "live" (e.g. -moz-element).
    289  void MarkContextClean();
    290 
    291  // Call this after capturing a frame, so we can avoid unnecessary surface
    292  // copies for future frames when no drawing has occurred.
    293  void MarkContextCleanForFrameCapture();
    294 
    295  // Returns non-null when the current context supports captureStream().
    296  // The FrameCaptureState gets set to DIRTY when something is drawn.
    297  Watchable<FrameCaptureState>* GetFrameCaptureState();
    298 
    299  nsresult GetContext(const nsAString& aContextId, nsISupports** aContext);
    300 
    301  layers::LayersBackend GetCompositorBackendType() const;
    302 
    303  void OnMemoryPressure();
    304  void OnDeviceReset();
    305 
    306  already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame();
    307  void ClearVRFrame();
    308 
    309  bool MaybeModified() const { return mMaybeModified; };
    310 
    311 protected:
    312  virtual ~HTMLCanvasElement();
    313  void Destroy();
    314 
    315  virtual JSObject* WrapNode(JSContext* aCx,
    316                             JS::Handle<JSObject*> aGivenProto) override;
    317 
    318  CSSIntSize GetWidthHeight() override;
    319 
    320  virtual already_AddRefed<nsICanvasRenderingContextInternal> CreateContext(
    321      CanvasContextType aContextType) override;
    322 
    323  nsresult UpdateContext(JSContext* aCx,
    324                         JS::Handle<JS::Value> aNewContextOptions,
    325                         ErrorResult& aRvForDictionaryInit) override;
    326 
    327  nsresult ExtractData(JSContext* aCx, nsIPrincipal& aSubjectPrincipal,
    328                       nsAString& aType, const nsAString& aOptions,
    329                       nsIInputStream** aStream);
    330  nsresult ToDataURLImpl(JSContext* aCx, nsIPrincipal& aSubjectPrincipal,
    331                         const nsAString& aMimeType,
    332                         const JS::Value& aEncoderOptions, nsAString& aDataURL);
    333 
    334  UniquePtr<uint8_t[]> GetImageBuffer(
    335      CanvasUtils::ImageExtraction aExtractionBehavior, int32_t* aOutFormat,
    336      gfx::IntSize* aOutImageSize) override;
    337 
    338  MOZ_CAN_RUN_SCRIPT void CallPrintCallback();
    339 
    340  virtual void AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
    341                            const nsAttrValue* aValue,
    342                            const nsAttrValue* aOldValue,
    343                            nsIPrincipal* aSubjectPrincipal,
    344                            bool aNotify) override;
    345  virtual void OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
    346                                      const nsAttrValueOrString& aValue,
    347                                      bool aNotify) override;
    348 
    349 public:
    350  ClientWebGLContext* GetWebGLContext();
    351  webgpu::CanvasContext* GetWebGPUContext();
    352 
    353  bool IsOffscreen() const { return !!mOffscreenCanvas; }
    354  OffscreenCanvas* GetOffscreenCanvas() const { return mOffscreenCanvas; }
    355  void FlushOffscreenCanvas();
    356 
    357  layers::ImageContainer* GetImageContainer() const { return mImageContainer; }
    358 
    359  bool UsingCaptureStream() const { return !!mRequestedFrameRefreshObserver; }
    360 
    361 protected:
    362  bool mResetLayer;
    363  bool mMaybeModified;  // we fetched the context, so we may have written to the
    364                        // canvas
    365  RefPtr<HTMLCanvasElement> mOriginalCanvas;
    366  RefPtr<PrintCallback> mPrintCallback;
    367  RefPtr<HTMLCanvasPrintState> mPrintState;
    368  nsTArray<WeakPtr<FrameCaptureListener>> mRequestedFrameListeners;
    369  RefPtr<RequestedFrameRefreshObserver> mRequestedFrameRefreshObserver;
    370  RefPtr<OffscreenCanvas> mOffscreenCanvas;
    371  RefPtr<OffscreenCanvasDisplayHelper> mOffscreenDisplay;
    372  RefPtr<layers::ImageContainer> mImageContainer;
    373  RefPtr<HTMLCanvasElementObserver> mContextObserver;
    374 
    375  // Record whether this canvas should be write-only or not.
    376  // We set this when script paints an image from a different origin.
    377  // We also transitively set it when script paints a canvas which
    378  // is itself write-only.
    379  bool mWriteOnly;
    380 
    381 public:
    382  // When this canvas is (only) tainted by an image from an extension
    383  // content script, allow reads from the same extension afterwards.
    384  RefPtr<nsIPrincipal> mExpandedReader;
    385 
    386  // Determines if the caller should be able to read the content.
    387  bool CallerCanRead(nsIPrincipal& aPrincipal) const;
    388 
    389  bool IsPrintCallbackDone();
    390 
    391  void HandlePrintCallback(nsPresContext*);
    392 
    393  nsresult DispatchPrintCallback(nsITimerCallback* aCallback);
    394 
    395  void ResetPrintCallback();
    396 
    397  HTMLCanvasElement* GetOriginalCanvas();
    398 
    399  CanvasContextType GetCurrentContextType();
    400 
    401 private:
    402  /**
    403   * This function is called by AfterSetAttr and OnAttrSetButNotChanged.
    404   * This function will be called by AfterSetAttr whether the attribute is being
    405   * set or unset.
    406   *
    407   * @param aNamespaceID the namespace of the attr being set
    408   * @param aName the localname of the attribute being set
    409   * @param aNotify Whether we plan to notify document observers.
    410   */
    411  void AfterMaybeChangeAttr(int32_t aNamespaceID, nsAtom* aName, bool aNotify);
    412 };
    413 
    414 class HTMLCanvasPrintState final : public nsWrapperCache {
    415 public:
    416  HTMLCanvasPrintState(HTMLCanvasElement* aCanvas,
    417                       nsICanvasRenderingContextInternal* aContext,
    418                       nsITimerCallback* aCallback);
    419 
    420  nsISupports* Context() const;
    421 
    422  void Done();
    423 
    424  void NotifyDone();
    425 
    426  bool mIsDone;
    427 
    428  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(HTMLCanvasPrintState)
    429  NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(HTMLCanvasPrintState)
    430 
    431  virtual JSObject* WrapObject(JSContext* cx,
    432                               JS::Handle<JSObject*> aGivenProto) override;
    433 
    434  HTMLCanvasElement* GetParentObject() { return mCanvas; }
    435 
    436 private:
    437  ~HTMLCanvasPrintState();
    438  bool mPendingNotify;
    439 
    440 protected:
    441  RefPtr<HTMLCanvasElement> mCanvas;
    442  nsCOMPtr<nsICanvasRenderingContextInternal> mContext;
    443  nsCOMPtr<nsITimerCallback> mCallback;
    444 };
    445 
    446 }  // namespace dom
    447 }  // namespace mozilla
    448 
    449 #endif /* mozilla_dom_HTMLCanvasElement_h */