Web Inspector: Instrument active pixel memory used by canvases
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Models / Canvas.js
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 WebInspector.Canvas = class Canvas extends WebInspector.Object
27 {
28     constructor(identifier, contextType, frame, {domNode, cssCanvasName, contextAttributes, memoryCost} = {})
29     {
30         super();
31
32         console.assert(identifier);
33         console.assert(contextType);
34         console.assert(frame instanceof WebInspector.Frame);
35
36         this._identifier = identifier;
37         this._contextType = contextType;
38         this._frame = frame;
39         this._domNode = domNode || null;
40         this._cssCanvasName = cssCanvasName || "";
41         this._contextAttributes = contextAttributes || {};
42         this._memoryCost = memoryCost || NaN;
43     }
44
45     // Static
46
47     static fromPayload(payload)
48     {
49         let contextType = null;
50         switch (payload.contextType) {
51         case CanvasAgent.ContextType.Canvas2D:
52             contextType = WebInspector.Canvas.ContextType.Canvas2D;
53             break;
54         case CanvasAgent.ContextType.WebGL:
55             contextType = WebInspector.Canvas.ContextType.WebGL;
56             break;
57         default:
58             console.error("Invalid canvas context type", payload.contextType);
59         }
60
61         let frame = WebInspector.frameResourceManager.frameForIdentifier(payload.frameId);
62         return new WebInspector.Canvas(payload.canvasId, contextType, frame, {
63             domNode: payload.nodeId ? WebInspector.domTreeManager.nodeForId(payload.nodeId) : null,
64             cssCanvasName: payload.cssCanvasName,
65             contextAttributes: payload.contextAttributes,
66             memoryCost: payload.memoryCost,
67         });
68     }
69
70     static displayNameForContextType(contextType)
71     {
72         switch (contextType) {
73         case WebInspector.Canvas.ContextType.Canvas2D:
74             return WebInspector.UIString("2D");
75         case WebInspector.Canvas.ContextType.WebGL:
76             return WebInspector.unlocalizedString("WebGL");
77         default:
78             console.error("Invalid canvas context type", contextType);
79         }
80     }
81
82     static resetUniqueDisplayNameNumbers()
83     {
84         WebInspector.Canvas._nextUniqueDisplayNameNumber = 1;
85     }
86
87     // Public
88
89     get identifier() { return this._identifier; }
90     get contextType() { return this._contextType; }
91     get frame() { return this._frame; }
92     get cssCanvasName() { return this._cssCanvasName; }
93     get contextAttributes() { return this._contextAttributes; }
94
95     get memoryCost()
96     {
97         return this._memoryCost;
98     }
99
100     set memoryCost(memoryCost)
101     {
102         if (memoryCost === this._memoryCost)
103             return;
104
105         this._memoryCost = memoryCost;
106
107         this.dispatchEventToListeners(WebInspector.Canvas.Event.MemoryChanged);
108     }
109
110     get displayName()
111     {
112         if (this._cssCanvasName)
113             return WebInspector.UIString("CSS canvas ā€œ%sā€").format(this._cssCanvasName);
114
115         if (this._domNode) {
116             let idSelector = this._domNode.escapedIdSelector;
117             if (idSelector)
118                 return WebInspector.UIString("Canvas %s").format(idSelector);
119         }
120
121         if (!this._uniqueDisplayNameNumber)
122             this._uniqueDisplayNameNumber = this.constructor._nextUniqueDisplayNameNumber++;
123         return WebInspector.UIString("Canvas %d").format(this._uniqueDisplayNameNumber);
124     }
125
126     requestNode(callback)
127     {
128         if (this._domNode) {
129             callback(this._domNode);
130             return;
131         }
132
133         WebInspector.domTreeManager.requestDocument((document) => {
134             CanvasAgent.requestNode(this._identifier, (error, nodeId) => {
135                 if (error) {
136                     callback(null);
137                     return;
138                 }
139
140                 this._domNode = WebInspector.domTreeManager.nodeForId(nodeId);
141                 callback(this._domNode);
142             });
143         });
144     }
145
146     requestContent(callback)
147     {
148         CanvasAgent.requestContent(this._identifier, (error, content) => {
149             if (error) {
150                 callback(null);
151                 return;
152             }
153
154             callback(content);
155         });
156     }
157
158     saveIdentityToCookie(cookie)
159     {
160         cookie[WebInspector.Canvas.FrameURLCookieKey] = this._frame.url.hash;
161
162         if (this._cssCanvasName)
163             cookie[WebInspector.Canvas.CSSCanvasNameCookieKey] = this._cssCanvasName;
164         else if (this._domNode)
165             cookie[WebInspector.Canvas.NodePathCookieKey] = this._domNode.path;
166
167     }
168 };
169
170 WebInspector.Canvas._nextUniqueDisplayNameNumber = 1;
171
172 WebInspector.Canvas.FrameURLCookieKey = "canvas-frame-url";
173 WebInspector.Canvas.CSSCanvasNameCookieKey = "canvas-css-canvas-name";
174
175 WebInspector.Canvas.ContextType = {
176     Canvas2D: "canvas-2d",
177     WebGL: "webgl",
178 };
179
180 WebInspector.Canvas.ResourceSidebarType = "resource-type-canvas";
181
182 WebInspector.Canvas.Event = {
183     MemoryChanged: "canvas-memory-changed",
184 };