0f87c4e5e088ce208feb64345ce1bbd833dcf103
[WebKit-https.git] / Source / WebCore / inspector / InjectedScript.cpp
1 /*
2  * Copyright (C) 2010, 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 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 #include "config.h"
32 #include "InjectedScript.h"
33
34 #if ENABLE(INSPECTOR)
35
36 #include "Frame.h"
37 #include "InjectedScriptHost.h"
38 #include "InjectedScriptManager.h"
39 #include "InspectorValues.h"
40 #include "Node.h"
41 #include "PlatformString.h"
42 #include "ScriptFunctionCall.h"
43
44 namespace WebCore {
45
46 InjectedScript::InjectedScript()
47     : m_inspectedStateAccessCheck(0)
48 {
49 }
50
51 InjectedScript::InjectedScript(ScriptObject injectedScriptObject, InspectedStateAccessCheck accessCheck)
52     : m_injectedScriptObject(injectedScriptObject)
53     , m_inspectedStateAccessCheck(accessCheck)
54 {
55 }
56
57 void InjectedScript::evaluate(ErrorString* errorString, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, RefPtr<InspectorObject>* result, bool* wasThrown)
58 {
59     ScriptFunctionCall function(m_injectedScriptObject, "evaluate");
60     function.appendArgument(expression);
61     function.appendArgument(objectGroup);
62     function.appendArgument(includeCommandLineAPI);
63     function.appendArgument(returnByValue);
64     makeEvalCall(errorString, function, result, wasThrown);
65 }
66
67 void InjectedScript::callFunctionOn(ErrorString* errorString, const String& objectId, const String& expression, const String& arguments, bool returnByValue, RefPtr<InspectorObject>* result, bool* wasThrown)
68 {
69     ScriptFunctionCall function(m_injectedScriptObject, "callFunctionOn");
70     function.appendArgument(objectId);
71     function.appendArgument(expression);
72     function.appendArgument(arguments);
73     function.appendArgument(returnByValue);
74     makeEvalCall(errorString, function, result, wasThrown);
75 }
76
77 void InjectedScript::evaluateOnCallFrame(ErrorString* errorString, const ScriptValue& callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, RefPtr<InspectorObject>* result, bool* wasThrown)
78 {
79     ScriptFunctionCall function(m_injectedScriptObject, "evaluateOnCallFrame");
80     function.appendArgument(callFrames);
81     function.appendArgument(callFrameId);
82     function.appendArgument(expression);
83     function.appendArgument(objectGroup);
84     function.appendArgument(includeCommandLineAPI);
85     function.appendArgument(returnByValue);
86     makeEvalCall(errorString, function, result, wasThrown);
87 }
88
89 void InjectedScript::getProperties(ErrorString* errorString, const String& objectId, bool ownProperties, RefPtr<InspectorArray>* properties)
90 {
91     ScriptFunctionCall function(m_injectedScriptObject, "getProperties");
92     function.appendArgument(objectId);
93     function.appendArgument(ownProperties);
94
95     RefPtr<InspectorValue> result;
96     makeCall(function, &result);
97     if (!result || result->type() != InspectorValue::TypeArray) {
98         *errorString = "Internal error";
99         return;
100     }
101     *properties = result->asArray();
102 }
103
104 Node* InjectedScript::nodeForObjectId(const String& objectId)
105 {
106     if (hasNoValue() || !canAccessInspectedWindow())
107         return 0;
108
109     ScriptFunctionCall function(m_injectedScriptObject, "nodeForObjectId");
110     function.appendArgument(objectId);
111
112     bool hadException = false;
113     ScriptValue resultValue = function.call(hadException);
114     ASSERT(!hadException);
115
116     return InjectedScriptHost::scriptValueAsNode(resultValue);
117 }
118
119 void InjectedScript::releaseObject(const String& objectId)
120 {
121     ScriptFunctionCall function(m_injectedScriptObject, "releaseObject");
122     function.appendArgument(objectId);
123     RefPtr<InspectorValue> result;
124     makeCall(function, &result);
125 }
126
127 #if ENABLE(JAVASCRIPT_DEBUGGER)
128 PassRefPtr<InspectorArray> InjectedScript::wrapCallFrames(const ScriptValue& callFrames)
129 {
130     ASSERT(!hasNoValue());
131     ScriptFunctionCall function(m_injectedScriptObject, "wrapCallFrames");
132     function.appendArgument(callFrames);
133     ScriptValue callFramesValue = function.call();
134     RefPtr<InspectorValue> result = callFramesValue.toInspectorValue(m_injectedScriptObject.scriptState());
135     if (result->type() == InspectorValue::TypeArray)
136         return result->asArray();
137     return InspectorArray::create();
138 }
139 #endif
140
141 PassRefPtr<InspectorObject> InjectedScript::wrapObject(ScriptValue value, const String& groupName)
142 {
143     ASSERT(!hasNoValue());
144     ScriptFunctionCall wrapFunction(m_injectedScriptObject, "wrapObject");
145     wrapFunction.appendArgument(value);
146     wrapFunction.appendArgument(groupName);
147     wrapFunction.appendArgument(canAccessInspectedWindow());
148     bool hadException = false;
149     ScriptValue r = wrapFunction.call(hadException);
150     if (hadException) {
151         RefPtr<InspectorObject> result = InspectorObject::create();
152         result->setString("description", "<exception>");
153         return result;
154     }
155     return r.toInspectorValue(m_injectedScriptObject.scriptState())->asObject();
156 }
157
158 PassRefPtr<InspectorObject> InjectedScript::wrapNode(Node* node, const String& groupName)
159 {
160     return wrapObject(nodeAsScriptValue(node), groupName);
161 }
162
163 void InjectedScript::inspectNode(Node* node)
164 {
165     ASSERT(!hasNoValue());
166     ScriptFunctionCall function(m_injectedScriptObject, "inspectNode");
167     function.appendArgument(nodeAsScriptValue(node));
168     RefPtr<InspectorValue> result;
169     makeCall(function, &result);
170 }
171
172 void InjectedScript::releaseObjectGroup(const String& objectGroup)
173 {
174     ASSERT(!hasNoValue());
175     ScriptFunctionCall releaseFunction(m_injectedScriptObject, "releaseObjectGroup");
176     releaseFunction.appendArgument(objectGroup);
177     releaseFunction.call();
178 }
179
180 bool InjectedScript::canAccessInspectedWindow()
181 {
182     return m_inspectedStateAccessCheck(m_injectedScriptObject.scriptState());
183 }
184
185 void InjectedScript::makeCall(ScriptFunctionCall& function, RefPtr<InspectorValue>* result)
186 {
187     if (hasNoValue() || !canAccessInspectedWindow()) {
188         *result = InspectorValue::null();
189         return;
190     }
191
192     bool hadException = false;
193     ScriptValue resultValue = function.call(hadException);
194
195     ASSERT(!hadException);
196     if (!hadException) {
197         *result = resultValue.toInspectorValue(m_injectedScriptObject.scriptState());
198         if (!*result)
199             *result = InspectorString::create(String::format("Object has too long reference chain(must not be longer than %d)", InspectorValue::maxDepth));
200     } else
201         *result = InspectorString::create("Exception while making a call.");
202 }
203
204 void InjectedScript::makeEvalCall(ErrorString* errorString, ScriptFunctionCall& function, RefPtr<InspectorObject>* objectResult, bool* wasThrown)
205 {
206     RefPtr<InspectorValue> result;
207     makeCall(function, &result);
208     if (!result) {
209         *errorString = "Internal error: result value is empty";
210         return;
211     }
212     if (result->type() == InspectorValue::TypeString) {
213         result->asString(errorString);
214         return;
215     }
216     RefPtr<InspectorObject> resultPair = result->asObject();
217     if (!resultPair) {
218         *errorString = "Internal error: result is not an Object";
219         return;
220     }
221     RefPtr<InspectorObject> resultObj = resultPair->getObject("result");
222     bool wasThrownVal = false;
223     if (!resultObj || !resultPair->getBoolean("wasThrown", &wasThrownVal)) {
224         *errorString = "Internal error: result is not a pair of value and wasThrown flag";
225         return;
226     }
227     *objectResult = resultObj;
228     *wasThrown = wasThrownVal;
229 }
230
231 ScriptValue InjectedScript::nodeAsScriptValue(Node* node)
232 {
233     return InjectedScriptHost::nodeAsScriptValue(m_injectedScriptObject.scriptState(), node);
234 }
235
236 } // namespace WebCore
237
238 #endif // ENABLE(INSPECTOR)