fcd4fb6177551687f560d6391d44ab720e93306a
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Protocol / RemoteObject.js
1 /*
2  * Copyright (C) 2009 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 copyright
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 WebInspector.RemoteObject = function(objectId, type, subtype, value, description)
32 {
33     this._type = type;
34     this._subtype = subtype;
35     if (objectId) {
36         // handle
37         this._objectId = objectId;
38         this._description = description;
39         this._hasChildren = true;
40     } else {
41         // Primitive or null object.
42         console.assert(type !== "object" || value === null);
43         this._description = description || (value + "");
44         this._hasChildren = false;
45         this.value = value;
46     }
47 };
48
49 WebInspector.RemoteObject.fromPrimitiveValue = function(value)
50 {
51     return new WebInspector.RemoteObject(undefined, typeof value, undefined, value);
52 };
53
54 WebInspector.RemoteObject.resolveNode = function(node, objectGroup, callback)
55 {
56     function mycallback(error, object)
57     {
58         if (!callback)
59             return;
60
61         if (error || !object)
62             callback(null);
63         else
64             callback(WebInspector.RemoteObject.fromPayload(object));
65     }
66     DOMAgent.resolveNode(node.id, objectGroup, mycallback);
67 };
68
69 WebInspector.RemoteObject.fromPayload = function(payload)
70 {
71     console.assert(typeof payload === "object", "Remote object payload should only be an object");
72
73     return new WebInspector.RemoteObject(payload.objectId, payload.type, payload.subtype, payload.value, payload.description);
74 };
75
76 WebInspector.RemoteObject.type = function(remoteObject)
77 {
78     if (remoteObject === null)
79         return "null";
80
81     var type = typeof remoteObject;
82     if (type !== "object" && type !== "function")
83         return type;
84
85     return remoteObject.type;
86 };
87
88 WebInspector.RemoteObject.prototype = {
89     get objectId()
90     {
91         return this._objectId;
92     },
93
94     get type()
95     {
96         return this._type;
97     },
98
99     get subtype()
100     {
101         return this._subtype;
102     },
103
104     get description()
105     {
106         return this._description;
107     },
108
109     get hasChildren()
110     {
111         return this._hasChildren;
112     },
113
114     getOwnProperties: function(callback)
115     {
116         this._getProperties(true, callback);
117     },
118
119     getAllProperties: function(callback)
120     {
121         this._getProperties(false, callback);
122     },
123
124     _getProperties: function(ownProperties, callback)
125     {
126         if (!this._objectId) {
127             callback([]);
128             return;
129         }
130
131         function remoteObjectBinder(error, properties)
132         {
133             if (error) {
134                 callback(null);
135                 return;
136             }
137             var result = [];
138             for (var i = 0; properties && i < properties.length; ++i) {
139                 var property = properties[i];
140                 if (property.get || property.set) {
141                     if (property.get)
142                         result.push(new WebInspector.RemoteObjectProperty("get " + property.name, WebInspector.RemoteObject.fromPayload(property.get), property));
143                     if (property.set)
144                         result.push(new WebInspector.RemoteObjectProperty("set " + property.name, WebInspector.RemoteObject.fromPayload(property.set), property));
145                 } else
146                     result.push(new WebInspector.RemoteObjectProperty(property.name, WebInspector.RemoteObject.fromPayload(property.value), property));
147             }
148             callback(result);
149         }
150         RuntimeAgent.getProperties(this._objectId, ownProperties, remoteObjectBinder);
151     },
152
153     setPropertyValue: function(name, value, callback)
154     {
155         if (!this._objectId) {
156             callback("Can't set a property of non-object.");
157             return;
158         }
159
160         RuntimeAgent.evaluate.invoke({expression:value, doNotPauseOnExceptionsAndMuteConsole:true}, evaluatedCallback.bind(this));
161
162         function evaluatedCallback(error, result, wasThrown)
163         {
164             if (error || wasThrown) {
165                 callback(error || result.description);
166                 return;
167             }
168
169             function setPropertyValue(propertyName, propertyValue)
170             {
171                 this[propertyName] = propertyValue;
172             }
173
174             delete result.description; // Optimize on traffic.
175             RuntimeAgent.callFunctionOn(this._objectId, setPropertyValue.toString(), [{ value:name }, result], true, undefined, propertySetCallback.bind(this));
176             if (result._objectId)
177                 RuntimeAgent.releaseObject(result._objectId);
178         }
179
180         function propertySetCallback(error, result, wasThrown)
181         {
182             if (error || wasThrown) {
183                 callback(error || result.description);
184                 return;
185             }
186             callback();
187         }
188     },
189
190     pushNodeToFrontend: function(callback)
191     {
192         if (this._objectId)
193             WebInspector.domTreeManager.pushNodeToFrontend(this._objectId, callback);
194         else
195             callback(0);
196     },
197
198     callFunction: function(functionDeclaration, args, callback)
199     {
200         function mycallback(error, result, wasThrown)
201         {
202             callback((error || wasThrown) ? null : WebInspector.RemoteObject.fromPayload(result));
203         }
204
205         RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), args, true, undefined, mycallback);
206     },
207
208     callFunctionJSON: function(functionDeclaration, args, callback)
209     {
210         function mycallback(error, result, wasThrown)
211         {
212             callback((error || wasThrown) ? null : result.value);
213         }
214
215         RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), args, true, true, mycallback);
216     },
217
218     release: function()
219     {
220         RuntimeAgent.releaseObject(this._objectId);
221     },
222
223     arrayLength: function()
224     {
225         if (this.subtype !== "array")
226             return 0;
227
228         var matches = this._description.match(/\[([0-9]+)\]/);
229         if (!matches)
230             return 0;
231         return parseInt(matches[1], 10);
232     }
233 };
234
235 WebInspector.RemoteObjectProperty = function(name, value, descriptor)
236 {
237     this.name = name;
238     this.value = value;
239     this.enumerable = descriptor ? !!descriptor.enumerable : true;
240     this.writable = descriptor ? !!descriptor.writable : true;
241     if (descriptor && descriptor.wasThrown)
242         this.wasThrown = true;
243 };
244
245 WebInspector.RemoteObjectProperty.fromPrimitiveValue = function(name, value)
246 {
247     return new WebInspector.RemoteObjectProperty(name, WebInspector.RemoteObject.fromPrimitiveValue(value));
248 };