Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / HeapSnapshotProxy.js
1 /*
2  * Copyright (C) 2011 Google 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyrightdd
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 /**
32  * @constructor
33  * @param {function(string, *)} eventHandler
34  * @extends {WebInspector.Object}
35  */
36 WebInspector.HeapSnapshotWorkerProxy = function(eventHandler)
37 {
38     this._eventHandler = eventHandler;
39     this._nextObjectId = 1;
40     this._nextCallId = 1;
41     this._callbacks = [];
42     this._previousCallbacks = [];
43     this._worker = new Worker("HeapSnapshotWorker.js");
44     this._worker.onmessage = this._messageReceived.bind(this);
45 }
46
47 WebInspector.HeapSnapshotWorkerProxy.prototype = {
48     /**
49      * @param {number} profileUid
50      * @param {function(!WebInspector.HeapSnapshotProxy)} snapshotReceivedCallback
51      * @return {!WebInspector.HeapSnapshotLoaderProxy}
52      */
53     createLoader: function(profileUid, snapshotReceivedCallback)
54     {
55         var objectId = this._nextObjectId++;
56         var proxy = new WebInspector.HeapSnapshotLoaderProxy(this, objectId, profileUid, snapshotReceivedCallback);
57         this._postMessage({callId: this._nextCallId++, disposition: "create", objectId: objectId, methodName: "WebInspector.HeapSnapshotLoader"});
58         return proxy;
59     },
60
61     dispose: function()
62     {
63         this._worker.terminate();
64         if (this._interval)
65             clearInterval(this._interval);
66     },
67
68     disposeObject: function(objectId)
69     {
70         this._postMessage({callId: this._nextCallId++, disposition: "dispose", objectId: objectId});
71     },
72
73     evaluateForTest: function(script, callback)
74     {
75         var callId = this._nextCallId++;
76         this._callbacks[callId] = callback;
77         this._postMessage({callId: callId, disposition: "evaluateForTest", source: script});
78     },
79
80     /**
81      * @param {?function(...[?])} callback
82      * @param {string} objectId
83      * @param {string} methodName
84      * @param {function(new:T, ...[?])} proxyConstructor
85      * @return {?Object}
86      * @template T
87      */
88     callFactoryMethod: function(callback, objectId, methodName, proxyConstructor)
89     {
90         var callId = this._nextCallId++;
91         var methodArguments = Array.prototype.slice.call(arguments, 4);
92         var newObjectId = this._nextObjectId++;
93
94         /**
95          * @this {WebInspector.HeapSnapshotWorkerProxy}
96          */
97         function wrapCallback(remoteResult)
98         {
99             callback(remoteResult ? new proxyConstructor(this, newObjectId) : null);
100         }
101
102         if (callback) {
103             this._callbacks[callId] = wrapCallback.bind(this);
104             this._postMessage({callId: callId, disposition: "factory", objectId: objectId, methodName: methodName, methodArguments: methodArguments, newObjectId: newObjectId});
105             return null;
106         } else {
107             this._postMessage({callId: callId, disposition: "factory", objectId: objectId, methodName: methodName, methodArguments: methodArguments, newObjectId: newObjectId});
108             return new proxyConstructor(this, newObjectId);
109         }
110     },
111
112     /**
113      * @param {function(*)} callback
114      * @param {string} objectId
115      * @param {string} methodName
116      */
117     callMethod: function(callback, objectId, methodName)
118     {
119         var callId = this._nextCallId++;
120         var methodArguments = Array.prototype.slice.call(arguments, 3);
121         if (callback)
122             this._callbacks[callId] = callback;
123         this._postMessage({callId: callId, disposition: "method", objectId: objectId, methodName: methodName, methodArguments: methodArguments});
124     },
125
126     startCheckingForLongRunningCalls: function()
127     {
128         if (this._interval)
129             return;
130         this._checkLongRunningCalls();
131         this._interval = setInterval(this._checkLongRunningCalls.bind(this), 300);
132     },
133
134     _checkLongRunningCalls: function()
135     {
136         for (var callId in this._previousCallbacks)
137             if (!(callId in this._callbacks))
138                 delete this._previousCallbacks[callId];
139         var hasLongRunningCalls = false;
140         for (callId in this._previousCallbacks) {
141             hasLongRunningCalls = true;
142             break;
143         }
144         this.dispatchEventToListeners("wait", hasLongRunningCalls);
145         for (callId in this._callbacks)
146             this._previousCallbacks[callId] = true;
147     },
148
149     /**
150      * @param {!MessageEvent} event
151      */
152     _messageReceived: function(event)
153     {
154         var data = event.data;
155         if (data.eventName) {
156             if (this._eventHandler)
157                 this._eventHandler(data.eventName, data.data);
158             return;
159         }
160         if (data.error) {
161             if (data.errorMethodName)
162                 WebInspector.console.log(WebInspector.UIString("An error happened when a call for method '%s' was requested", data.errorMethodName));
163             WebInspector.console.log(data["errorCallStack"]);
164             delete this._callbacks[data.callId];
165             return;
166         }
167         if (!this._callbacks[data.callId])
168             return;
169         var callback = this._callbacks[data.callId];
170         delete this._callbacks[data.callId];
171         callback(data.result);
172     },
173
174     _postMessage: function(message)
175     {
176         this._worker.postMessage(message);
177     },
178
179     __proto__: WebInspector.Object.prototype
180 }
181
182
183 /**
184  * @constructor
185  * @param {number} objectId
186  */
187 WebInspector.HeapSnapshotProxyObject = function(worker, objectId)
188 {
189     this._worker = worker;
190     this._objectId = objectId;
191 }
192
193 WebInspector.HeapSnapshotProxyObject.prototype = {
194     /**
195      * @param {string} workerMethodName
196      * @param {!Array.<*>} args
197      */
198     _callWorker: function(workerMethodName, args)
199     {
200         args.splice(1, 0, this._objectId);
201         return this._worker[workerMethodName].apply(this._worker, args);
202     },
203
204     dispose: function()
205     {
206         this._worker.disposeObject(this._objectId);
207     },
208
209     disposeWorker: function()
210     {
211         this._worker.dispose();
212     },
213
214     /**
215      * @param {?function(...[?])} callback
216      * @param {string} methodName
217      * @param {function (new:T, ...[?])} proxyConstructor
218      * @param {...*} var_args
219      * @return {!T}
220      * @template T
221      */
222     callFactoryMethod: function(callback, methodName, proxyConstructor, var_args)
223     {
224         return this._callWorker("callFactoryMethod", Array.prototype.slice.call(arguments, 0));
225     },
226
227     /**
228      * @param {function(T)|undefined} callback
229      * @param {string} methodName
230      * @param {...*} var_args
231      * @return {*}
232      * @template T
233      */
234     callMethod: function(callback, methodName, var_args)
235     {
236         return this._callWorker("callMethod", Array.prototype.slice.call(arguments, 0));
237     }
238 };
239
240 /**
241  * @constructor
242  * @extends {WebInspector.HeapSnapshotProxyObject}
243  * @implements {WebInspector.OutputStream}
244  * @param {number} objectId
245  * @param {number} profileUid
246  * @param {function(!WebInspector.HeapSnapshotProxy)} snapshotReceivedCallback
247  */
248 WebInspector.HeapSnapshotLoaderProxy = function(worker, objectId, profileUid, snapshotReceivedCallback)
249 {
250     WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId);
251     this._profileUid = profileUid;
252     this._snapshotReceivedCallback = snapshotReceivedCallback;
253 }
254
255 WebInspector.HeapSnapshotLoaderProxy.prototype = {
256     /**
257      * @param {string} chunk
258      * @param {function(!WebInspector.OutputStream)=} callback
259      */
260     write: function(chunk, callback)
261     {
262         this.callMethod(callback, "write", chunk);
263     },
264
265     /**
266      * @param {function()=} callback
267      */
268     close: function(callback)
269     {
270         /**
271          * @this {WebInspector.HeapSnapshotLoaderProxy}
272          */
273         function buildSnapshot()
274         {
275             if (callback)
276                 callback();
277             var showHiddenData = WebInspector.settings.showAdvancedHeapSnapshotProperties.get();
278             this.callFactoryMethod(updateStaticData.bind(this), "buildSnapshot", WebInspector.HeapSnapshotProxy, showHiddenData);
279         }
280
281         /**
282          * @param {!WebInspector.HeapSnapshotProxy} snapshotProxy
283          * @this {WebInspector.HeapSnapshotLoaderProxy}
284          */
285         function updateStaticData(snapshotProxy)
286         {
287             this.dispose();
288             snapshotProxy.setProfileUid(this._profileUid);
289             snapshotProxy.updateStaticData(this._snapshotReceivedCallback.bind(this));
290         }
291
292         this.callMethod(buildSnapshot.bind(this), "close");
293     },
294
295     __proto__: WebInspector.HeapSnapshotProxyObject.prototype
296 }
297
298
299 /**
300  * @constructor
301  * @extends {WebInspector.HeapSnapshotProxyObject}
302  * @param {!WebInspector.HeapSnapshotWorkerProxy} worker
303  * @param {number} objectId
304  */
305 WebInspector.HeapSnapshotProxy = function(worker, objectId)
306 {
307     WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId);
308     /** @type {?WebInspector.HeapSnapshotCommon.StaticData} */
309     this._staticData = null;
310 }
311
312 WebInspector.HeapSnapshotProxy.prototype = {
313     /**
314      * @param {!WebInspector.HeapSnapshotCommon.NodeFilter} filter
315      * @param {function(!Object.<string, !WebInspector.HeapSnapshotCommon.Aggregate>)} callback
316      */
317     aggregatesWithFilter: function(filter, callback)
318     {
319         this.callMethod(callback, "aggregatesWithFilter", filter);
320     },
321
322     aggregatesForDiff: function(callback)
323     {
324         this.callMethod(callback, "aggregatesForDiff");
325     },
326
327     calculateSnapshotDiff: function(baseSnapshotId, baseSnapshotAggregates, callback)
328     {
329         this.callMethod(callback, "calculateSnapshotDiff", baseSnapshotId, baseSnapshotAggregates);
330     },
331
332     nodeClassName: function(snapshotObjectId, callback)
333     {
334         this.callMethod(callback, "nodeClassName", snapshotObjectId);
335     },
336
337     dominatorIdsForNode: function(nodeIndex, callback)
338     {
339         this.callMethod(callback, "dominatorIdsForNode", nodeIndex);
340     },
341
342     /**
343      * @param {number} nodeIndex
344      * @return {!WebInspector.HeapSnapshotProviderProxy}
345      */
346     createEdgesProvider: function(nodeIndex)
347     {
348         return this.callFactoryMethod(null, "createEdgesProvider", WebInspector.HeapSnapshotProviderProxy, nodeIndex);
349     },
350
351     /**
352      * @param {number} nodeIndex
353      * @return {!WebInspector.HeapSnapshotProviderProxy}
354      */
355     createRetainingEdgesProvider: function(nodeIndex)
356     {
357         return this.callFactoryMethod(null, "createRetainingEdgesProvider", WebInspector.HeapSnapshotProviderProxy, nodeIndex);
358     },
359
360     /**
361      * @param {string} baseSnapshotId
362      * @param {string} className
363      * @return {?WebInspector.HeapSnapshotProviderProxy}
364      */
365     createAddedNodesProvider: function(baseSnapshotId, className)
366     {
367         return this.callFactoryMethod(null, "createAddedNodesProvider", WebInspector.HeapSnapshotProviderProxy, baseSnapshotId, className);
368     },
369
370     /**
371      * @param {!Array.<number>} nodeIndexes
372      * @return {?WebInspector.HeapSnapshotProviderProxy}
373      */
374     createDeletedNodesProvider: function(nodeIndexes)
375     {
376         return this.callFactoryMethod(null, "createDeletedNodesProvider", WebInspector.HeapSnapshotProviderProxy, nodeIndexes);
377     },
378
379     /**
380      * @param {function(*):boolean} filter
381      * @return {?WebInspector.HeapSnapshotProviderProxy}
382      */
383     createNodesProvider: function(filter)
384     {
385         return this.callFactoryMethod(null, "createNodesProvider", WebInspector.HeapSnapshotProviderProxy, filter);
386     },
387
388     /**
389      * @param {string} className
390      * @param {!WebInspector.HeapSnapshotCommon.NodeFilter} nodeFilter
391      * @return {?WebInspector.HeapSnapshotProviderProxy}
392      */
393     createNodesProviderForClass: function(className, nodeFilter)
394     {
395         return this.callFactoryMethod(null, "createNodesProviderForClass", WebInspector.HeapSnapshotProviderProxy, className, nodeFilter);
396     },
397
398     /**
399      * @param {number} nodeIndex
400      * @return {?WebInspector.HeapSnapshotProviderProxy}
401      */
402     createNodesProviderForDominator: function(nodeIndex)
403     {
404         return this.callFactoryMethod(null, "createNodesProviderForDominator", WebInspector.HeapSnapshotProviderProxy, nodeIndex);
405     },
406
407     allocationTracesTops: function(callback)
408     {
409         this.callMethod(callback, "allocationTracesTops");
410     },
411
412     /**
413      * @param {number} nodeId
414      * @param {function(!WebInspector.HeapSnapshotCommon.AllocationNodeCallers)} callback
415      */
416     allocationNodeCallers: function(nodeId, callback)
417     {
418         this.callMethod(callback, "allocationNodeCallers", nodeId);
419     },
420
421     dispose: function()
422     {
423         throw new Error("Should never be called");
424     },
425
426     get nodeCount()
427     {
428         return this._staticData.nodeCount;
429     },
430
431     get rootNodeIndex()
432     {
433         return this._staticData.rootNodeIndex;
434     },
435
436     updateStaticData: function(callback)
437     {
438         /**
439          * @param {!WebInspector.HeapSnapshotCommon.StaticData} staticData
440          * @this {WebInspector.HeapSnapshotProxy}
441          */
442         function dataReceived(staticData)
443         {
444             this._staticData = staticData;
445             callback(this);
446         }
447         this.callMethod(dataReceived.bind(this), "updateStaticData");
448     },
449
450     /**
451      * @param {!function(!WebInspector.HeapSnapshotCommon.Statistics):void} callback
452      */
453     getStatistics: function(callback)
454     {
455         this.callMethod(callback, "getStatistics");
456     },
457
458     get totalSize()
459     {
460         return this._staticData.totalSize;
461     },
462
463     get uid()
464     {
465         return this._profileUid;
466     },
467
468     setProfileUid: function(profileUid)
469     {
470         this._profileUid = profileUid;
471     },
472
473     /**
474      * @return {number}
475      */
476     maxJSObjectId: function()
477     {
478         return this._staticData.maxJSObjectId;
479     },
480
481     __proto__: WebInspector.HeapSnapshotProxyObject.prototype
482 }
483
484
485 /**
486  * @constructor
487  * @extends {WebInspector.HeapSnapshotProxyObject}
488  * @implements {WebInspector.HeapSnapshotGridNode.ChildrenProvider}
489  * @param {!WebInspector.HeapSnapshotWorkerProxy} worker
490  * @param {number} objectId
491  */
492 WebInspector.HeapSnapshotProviderProxy = function(worker, objectId)
493 {
494     WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId);
495 }
496
497 WebInspector.HeapSnapshotProviderProxy.prototype = {
498     /**
499      * @override
500      * @param {number} snapshotObjectId
501      * @param {function(number)} callback
502      */
503     nodePosition: function(snapshotObjectId, callback)
504     {
505         this.callMethod(callback, "nodePosition", snapshotObjectId);
506     },
507
508     /**
509      * @override
510      * @param {function(boolean)} callback
511      */
512     isEmpty: function(callback)
513     {
514         this.callMethod(callback, "isEmpty");
515     },
516
517     /**
518      * @override
519      * @param {number} startPosition
520      * @param {number} endPosition
521      * @param {function(!WebInspector.HeapSnapshotCommon.ItemsRange)} callback
522      */
523     serializeItemsRange: function(startPosition, endPosition, callback)
524     {
525         this.callMethod(callback, "serializeItemsRange", startPosition, endPosition);
526     },
527
528     /**
529      * @override
530      * @param {!WebInspector.HeapSnapshotCommon.ComparatorConfig} comparator
531      * @param {function()} callback
532      */
533     sortAndRewind: function(comparator, callback)
534     {
535         this.callMethod(callback, "sortAndRewind", comparator);
536     },
537
538     __proto__: WebInspector.HeapSnapshotProxyObject.prototype
539 }