/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 */ |