Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/dom/HTMLCanvasElement.h
Line
Count
Source (jump to first uncovered line)
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
#if !defined(mozilla_dom_HTMLCanvasElement_h)
7
#define mozilla_dom_HTMLCanvasElement_h
8
9
#include "mozilla/Attributes.h"
10
#include "mozilla/WeakPtr.h"
11
#include "nsIDOMEventListener.h"
12
#include "nsIObserver.h"
13
#include "nsGenericHTMLElement.h"
14
#include "nsGkAtoms.h"
15
#include "nsSize.h"
16
#include "nsError.h"
17
18
#include "mozilla/dom/BindingDeclarations.h"
19
#include "mozilla/dom/CanvasRenderingContextHelper.h"
20
#include "mozilla/gfx/Rect.h"
21
#include "mozilla/layers/LayersTypes.h"
22
23
class nsICanvasRenderingContextInternal;
24
class nsITimerCallback;
25
26
namespace mozilla {
27
28
class WebGLContext;
29
30
namespace layers {
31
class AsyncCanvasRenderer;
32
class CanvasRenderer;
33
class CanvasLayer;
34
class Image;
35
class Layer;
36
class LayerManager;
37
class SharedSurfaceTextureClient;
38
class WebRenderCanvasData;
39
} // namespace layers
40
namespace gfx {
41
class SourceSurface;
42
class VRLayerChild;
43
} // namespace gfx
44
45
namespace dom {
46
class BlobCallback;
47
class CanvasCaptureMediaStream;
48
class File;
49
class HTMLCanvasPrintState;
50
class OffscreenCanvas;
51
class PrintCallback;
52
class RequestedFrameRefreshObserver;
53
54
// Listen visibilitychange and memory-pressure event and inform
55
// context when event is fired.
56
class HTMLCanvasElementObserver final : public nsIObserver
57
                                      , public nsIDOMEventListener
58
{
59
public:
60
  NS_DECL_ISUPPORTS
61
  NS_DECL_NSIOBSERVER
62
  NS_DECL_NSIDOMEVENTLISTENER
63
64
  explicit HTMLCanvasElementObserver(HTMLCanvasElement* aElement);
65
  void Destroy();
66
67
  void RegisterVisibilityChangeEvent();
68
  void UnregisterVisibilityChangeEvent();
69
70
  void RegisterMemoryPressureEvent();
71
  void UnregisterMemoryPressureEvent();
72
73
private:
74
  ~HTMLCanvasElementObserver();
75
76
  HTMLCanvasElement* mElement;
77
};
78
79
/*
80
 * FrameCaptureListener is used by captureStream() as a way of getting video
81
 * frames from the canvas. On a refresh driver tick after something has been
82
 * drawn to the canvas since the last such tick, all registered
83
 * FrameCaptureListeners whose `mFrameCaptureRequested` equals `true`,
84
 * will be given a copy of the just-painted canvas.
85
 * All FrameCaptureListeners get the same copy.
86
 */
87
class FrameCaptureListener : public SupportsWeakPtr<FrameCaptureListener>
88
{
89
public:
90
  MOZ_DECLARE_WEAKREFERENCE_TYPENAME(FrameCaptureListener)
91
92
  FrameCaptureListener()
93
0
    : mFrameCaptureRequested(false) {}
94
95
  /*
96
   * Called when a frame capture is desired on next paint.
97
   */
98
0
  void RequestFrameCapture() { mFrameCaptureRequested = true; }
99
100
  /*
101
   * Indicates to the canvas whether or not this listener has requested a frame.
102
   */
103
0
  bool FrameCaptureRequested() const { return mFrameCaptureRequested; }
104
105
  /*
106
   * Interface through which new video frames will be provided while
107
   * `mFrameCaptureRequested` is `true`.
108
   */
109
  virtual void NewFrame(already_AddRefed<layers::Image> aImage,
110
                        const TimeStamp& aTime) = 0;
111
112
protected:
113
0
  virtual ~FrameCaptureListener() {}
114
115
  bool mFrameCaptureRequested;
116
};
117
118
class HTMLCanvasElement final : public nsGenericHTMLElement,
119
                                public CanvasRenderingContextHelper
120
{
121
  enum {
122
    DEFAULT_CANVAS_WIDTH = 300,
123
    DEFAULT_CANVAS_HEIGHT = 150
124
  };
125
126
  typedef layers::AsyncCanvasRenderer AsyncCanvasRenderer;
127
  typedef layers::CanvasRenderer CanvasRenderer;
128
  typedef layers::CanvasLayer CanvasLayer;
129
  typedef layers::Layer Layer;
130
  typedef layers::LayerManager LayerManager;
131
  typedef layers::WebRenderCanvasData WebRenderCanvasData;
132
133
public:
134
  explicit HTMLCanvasElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
135
136
  NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLCanvasElement, canvas)
137
138
  // nsISupports
139
  NS_DECL_ISUPPORTS_INHERITED
140
141
  // CC
142
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLCanvasElement,
143
                                           nsGenericHTMLElement)
144
145
  // WebIDL
146
  uint32_t Height()
147
0
  {
148
0
    return GetUnsignedIntAttr(nsGkAtoms::height, DEFAULT_CANVAS_HEIGHT);
149
0
  }
150
  void SetHeight(uint32_t aHeight, ErrorResult& aRv)
151
0
  {
152
0
    if (mOffscreenCanvas) {
153
0
      aRv.Throw(NS_ERROR_FAILURE);
154
0
      return;
155
0
    }
156
0
157
0
    SetUnsignedIntAttr(nsGkAtoms::height, aHeight, DEFAULT_CANVAS_HEIGHT, aRv);
158
0
  }
159
  uint32_t Width()
160
0
  {
161
0
    return GetUnsignedIntAttr(nsGkAtoms::width, DEFAULT_CANVAS_WIDTH);
162
0
  }
163
  void SetWidth(uint32_t aWidth, ErrorResult& aRv)
164
0
  {
165
0
    if (mOffscreenCanvas) {
166
0
      aRv.Throw(NS_ERROR_FAILURE);
167
0
      return;
168
0
    }
169
0
170
0
    SetUnsignedIntAttr(nsGkAtoms::width, aWidth, DEFAULT_CANVAS_WIDTH, aRv);
171
0
  }
172
173
  virtual already_AddRefed<nsISupports>
174
  GetContext(JSContext* aCx, const nsAString& aContextId,
175
             JS::Handle<JS::Value> aContextOptions,
176
             ErrorResult& aRv) override;
177
178
  void ToDataURL(JSContext* aCx, const nsAString& aType,
179
                 JS::Handle<JS::Value> aParams,
180
                 nsAString& aDataURL,
181
                 nsIPrincipal& aSubjectPrincipal,
182
                 ErrorResult& aRv);
183
184
  void ToBlob(JSContext* aCx,
185
              BlobCallback& aCallback,
186
              const nsAString& aType,
187
              JS::Handle<JS::Value> aParams,
188
              nsIPrincipal& aSubjectPrincipal,
189
              ErrorResult& aRv);
190
191
  OffscreenCanvas* TransferControlToOffscreen(ErrorResult& aRv);
192
193
  bool MozOpaque() const
194
0
  {
195
0
    return GetBoolAttr(nsGkAtoms::moz_opaque);
196
0
  }
197
  void SetMozOpaque(bool aValue, ErrorResult& aRv)
198
0
  {
199
0
    if (mOffscreenCanvas) {
200
0
      aRv.Throw(NS_ERROR_FAILURE);
201
0
      return;
202
0
    }
203
0
204
0
    SetHTMLBoolAttr(nsGkAtoms::moz_opaque, aValue, aRv);
205
0
  }
206
  already_AddRefed<File> MozGetAsFile(const nsAString& aName,
207
                                      const nsAString& aType,
208
                                      nsIPrincipal& aSubjectPrincipal,
209
                                      ErrorResult& aRv);
210
  already_AddRefed<nsISupports> MozGetIPCContext(const nsAString& aContextId,
211
                                                 ErrorResult& aRv);
212
  PrintCallback* GetMozPrintCallback() const;
213
  void SetMozPrintCallback(PrintCallback* aCallback);
214
215
  already_AddRefed<CanvasCaptureMediaStream>
216
  CaptureStream(const Optional<double>& aFrameRate, nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
217
218
  /**
219
   * Get the size in pixels of this canvas element
220
   */
221
  nsIntSize GetSize();
222
223
  /**
224
   * Determine whether the canvas is write-only.
225
   */
226
  bool IsWriteOnly();
227
228
  /**
229
   * Force the canvas to be write-only.
230
   */
231
  void SetWriteOnly();
232
233
  /**
234
   * Notify that some canvas content has changed and the window may
235
   * need to be updated. aDamageRect is in canvas coordinates.
236
   */
237
  void InvalidateCanvasContent(const mozilla::gfx::Rect* aDamageRect);
238
  /*
239
   * Notify that we need to repaint the entire canvas, including updating of
240
   * the layer tree.
241
   */
242
  void InvalidateCanvas();
243
244
  /*
245
   * Get the number of contexts in this canvas, and request a context at
246
   * an index.
247
   */
248
  int32_t CountContexts ();
249
  nsICanvasRenderingContextInternal *GetContextAtIndex (int32_t index);
250
251
  /*
252
   * Returns true if the canvas context content is guaranteed to be opaque
253
   * across its entire area.
254
   */
255
  bool GetIsOpaque();
256
  virtual bool GetOpaqueAttr() override;
257
258
  virtual already_AddRefed<gfx::SourceSurface>
259
  GetSurfaceSnapshot(gfxAlphaType* aOutAlphaType = nullptr);
260
261
  /*
262
   * Register a FrameCaptureListener with this canvas.
263
   * The canvas hooks into the RefreshDriver while there are
264
   * FrameCaptureListeners registered.
265
   * The registered FrameCaptureListeners are stored as WeakPtrs, thus it's the
266
   * caller's responsibility to keep them alive. Once a registered
267
   * FrameCaptureListener is destroyed it will be automatically deregistered.
268
   */
269
  nsresult RegisterFrameCaptureListener(FrameCaptureListener* aListener,
270
                                        bool aReturnPlaceholderData);
271
272
  /*
273
   * Returns true when there is at least one registered FrameCaptureListener
274
   * that has requested a frame capture.
275
   */
276
  bool IsFrameCaptureRequested() const;
277
278
  /*
279
   * Processes destroyed FrameCaptureListeners and removes them if necessary.
280
   * Should there be none left, the FrameRefreshObserver will be unregistered.
281
   */
282
  void ProcessDestroyedFrameListeners();
283
284
  /*
285
   * Called by the RefreshDriver hook when a frame has been captured.
286
   * Makes a copy of the provided surface and hands it to all
287
   * FrameCaptureListeners having requested frame capture.
288
   */
289
  void SetFrameCapture(already_AddRefed<gfx::SourceSurface> aSurface,
290
                       const TimeStamp& aTime);
291
292
  virtual bool ParseAttribute(int32_t aNamespaceID,
293
                                nsAtom* aAttribute,
294
                                const nsAString& aValue,
295
                                nsIPrincipal* aMaybeScriptedPrincipal,
296
                                nsAttrValue& aResult) override;
297
  nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute, int32_t aModType) const override;
298
299
  virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
300
  nsresult CopyInnerTo(HTMLCanvasElement* aDest);
301
302
  void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
303
304
  /*
305
   * Helpers called by various users of Canvas
306
   */
307
308
  already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
309
                                         Layer *aOldLayer,
310
                                         LayerManager *aManager);
311
  bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
312
                                 WebRenderCanvasData* aCanvasData);
313
  bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
314
                                CanvasRenderer* aRenderer);
315
  // Should return true if the canvas layer should always be marked inactive.
316
  // We should return true here if we can't do accelerated compositing with
317
  // a non-BasicCanvasLayer.
318
  bool ShouldForceInactiveLayer(LayerManager *aManager);
319
320
  // Call this whenever we need future changes to the canvas
321
  // to trigger fresh invalidation requests. This needs to be called
322
  // whenever we render the canvas contents to the screen, or whenever we
323
  // take a snapshot of the canvas that needs to be "live" (e.g. -moz-element).
324
  void MarkContextClean();
325
326
  // Call this after capturing a frame, so we can avoid unnecessary surface
327
  // copies for future frames when no drawing has occurred.
328
  void MarkContextCleanForFrameCapture();
329
330
  // Starts returning false when something is drawn.
331
  bool IsContextCleanForFrameCapture();
332
333
  nsresult GetContext(const nsAString& aContextId, nsISupports** aContext);
334
335
  layers::LayersBackend GetCompositorBackendType() const;
336
337
  void OnVisibilityChange();
338
339
  void OnMemoryPressure();
340
341
  static void SetAttrFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer);
342
  static void InvalidateFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer);
343
344
  already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame();
345
346
protected:
347
  virtual ~HTMLCanvasElement();
348
349
  virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
350
351
  virtual nsIntSize GetWidthHeight() override;
352
353
  virtual already_AddRefed<nsICanvasRenderingContextInternal>
354
  CreateContext(CanvasContextType aContextType) override;
355
356
  nsresult ExtractData(JSContext* aCx,
357
                       nsIPrincipal& aSubjectPrincipal,
358
                       nsAString& aType,
359
                       const nsAString& aOptions,
360
                       nsIInputStream** aStream);
361
  nsresult ToDataURLImpl(JSContext* aCx,
362
                         nsIPrincipal& aSubjectPrincipal,
363
                         const nsAString& aMimeType,
364
                         const JS::Value& aEncoderOptions,
365
                         nsAString& aDataURL);
366
  nsresult MozGetAsFileImpl(const nsAString& aName,
367
                            const nsAString& aType,
368
                            nsIPrincipal& aSubjectPrincipal,
369
                            File** aResult);
370
  void CallPrintCallback();
371
372
  virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
373
                                const nsAttrValue* aValue,
374
                                const nsAttrValue* aOldValue,
375
                                nsIPrincipal* aSubjectPrincipal,
376
                                bool aNotify) override;
377
  virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
378
                                          const nsAttrValueOrString& aValue,
379
                                          bool aNotify) override;
380
381
  AsyncCanvasRenderer* GetAsyncCanvasRenderer();
382
383
  bool mResetLayer;
384
  RefPtr<HTMLCanvasElement> mOriginalCanvas;
385
  RefPtr<PrintCallback> mPrintCallback;
386
  RefPtr<HTMLCanvasPrintState> mPrintState;
387
  nsTArray<WeakPtr<FrameCaptureListener>> mRequestedFrameListeners;
388
  RefPtr<RequestedFrameRefreshObserver> mRequestedFrameRefreshObserver;
389
  RefPtr<AsyncCanvasRenderer> mAsyncCanvasRenderer;
390
  RefPtr<OffscreenCanvas> mOffscreenCanvas;
391
  RefPtr<HTMLCanvasElementObserver> mContextObserver;
392
393
public:
394
  // Record whether this canvas should be write-only or not.
395
  // We set this when script paints an image from a different origin.
396
  // We also transitively set it when script paints a canvas which
397
  // is itself write-only.
398
  bool                     mWriteOnly;
399
400
  bool IsPrintCallbackDone();
401
402
  void HandlePrintCallback(nsPresContext::nsPresContextType aType);
403
404
  nsresult DispatchPrintCallback(nsITimerCallback* aCallback);
405
406
  void ResetPrintCallback();
407
408
  HTMLCanvasElement* GetOriginalCanvas();
409
410
0
  CanvasContextType GetCurrentContextType() {
411
0
    return mCurrentContextType;
412
0
  }
413
414
private:
415
  /**
416
   * This function is called by AfterSetAttr and OnAttrSetButNotChanged.
417
   * This function will be called by AfterSetAttr whether the attribute is being
418
   * set or unset.
419
   *
420
   * @param aNamespaceID the namespace of the attr being set
421
   * @param aName the localname of the attribute being set
422
   * @param aNotify Whether we plan to notify document observers.
423
   */
424
  void AfterMaybeChangeAttr(int32_t aNamespaceID, nsAtom* aName, bool aNotify);
425
};
426
427
class HTMLCanvasPrintState final : public nsWrapperCache
428
{
429
public:
430
  HTMLCanvasPrintState(HTMLCanvasElement* aCanvas,
431
                       nsICanvasRenderingContextInternal* aContext,
432
                       nsITimerCallback* aCallback);
433
434
  nsISupports* Context() const;
435
436
  void Done();
437
438
  void NotifyDone();
439
440
  bool mIsDone;
441
442
  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(HTMLCanvasPrintState)
443
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(HTMLCanvasPrintState)
444
445
  virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
446
447
  HTMLCanvasElement* GetParentObject()
448
0
  {
449
0
    return mCanvas;
450
0
  }
451
452
private:
453
  ~HTMLCanvasPrintState();
454
  bool mPendingNotify;
455
456
protected:
457
  RefPtr<HTMLCanvasElement> mCanvas;
458
  nsCOMPtr<nsICanvasRenderingContextInternal> mContext;
459
  nsCOMPtr<nsITimerCallback> mCallback;
460
};
461
462
} // namespace dom
463
} // namespace mozilla
464
465
#endif /* mozilla_dom_HTMLCanvasElement_h */