1 /* 2 * Copyright (C) 2012 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 33 34 #include "core/inspector/InjectedScript.h" 35 36 #include "bindings/v8/ScriptFunctionCall.h" 37 #include "core/inspector/InjectedScriptHost.h" 38 #include "platform/JSONValues.h" 39 #include "wtf/text/WTFString.h" 40 41 using WebCore::TypeBuilder::Array; 42 using WebCore::TypeBuilder::Debugger::CallFrame; 43 using WebCore::TypeBuilder::Runtime::PropertyDescriptor; 44 using WebCore::TypeBuilder::Runtime::InternalPropertyDescriptor; 45 using WebCore::TypeBuilder::Debugger::FunctionDetails; 46 using WebCore::TypeBuilder::Runtime::RemoteObject; 47 48 namespace WebCore { 49 50 InjectedScript::InjectedScript() 51 : InjectedScriptBase("InjectedScript") 52 { 53 } 54 55 InjectedScript::InjectedScript(ScriptObject injectedScriptObject, InspectedStateAccessCheck accessCheck) 56 : InjectedScriptBase("InjectedScript", injectedScriptObject, accessCheck) 57 { 58 } 59 60 void InjectedScript::evaluate(ErrorString* errorString, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, RefPtr<TypeBuilder::Runtime::RemoteObject>* result, TypeBuilder::OptOutput<bool>* wasThrown) 61 { 62 ScriptFunctionCall function(injectedScriptObject(), "evaluate"); 63 function.appendArgument(expression); 64 function.appendArgument(objectGroup); 65 function.appendArgument(includeCommandLineAPI); 66 function.appendArgument(returnByValue); 67 function.appendArgument(generatePreview); 68 makeEvalCall(errorString, function, result, wasThrown); 69 } 70 71 void InjectedScript::callFunctionOn(ErrorString* errorString, const String& objectId, const String& expression, const String& arguments, bool returnByValue, bool generatePreview, RefPtr<TypeBuilder::Runtime::RemoteObject>* result, TypeBuilder::OptOutput<bool>* wasThrown) 72 { 73 ScriptFunctionCall function(injectedScriptObject(), "callFunctionOn"); 74 function.appendArgument(objectId); 75 function.appendArgument(expression); 76 function.appendArgument(arguments); 77 function.appendArgument(returnByValue); 78 function.appendArgument(generatePreview); 79 makeEvalCall(errorString, function, result, wasThrown); 80 } 81 82 void InjectedScript::evaluateOnCallFrame(ErrorString* errorString, const ScriptValue& callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, RefPtr<RemoteObject>* result, TypeBuilder::OptOutput<bool>* wasThrown) 83 { 84 ScriptFunctionCall function(injectedScriptObject(), "evaluateOnCallFrame"); 85 function.appendArgument(callFrames); 86 function.appendArgument(callFrameId); 87 function.appendArgument(expression); 88 function.appendArgument(objectGroup); 89 function.appendArgument(includeCommandLineAPI); 90 function.appendArgument(returnByValue); 91 function.appendArgument(generatePreview); 92 makeEvalCall(errorString, function, result, wasThrown); 93 } 94 95 void InjectedScript::restartFrame(ErrorString* errorString, const ScriptValue& callFrames, const String& callFrameId, RefPtr<JSONObject>* result) 96 { 97 ScriptFunctionCall function(injectedScriptObject(), "restartFrame"); 98 function.appendArgument(callFrames); 99 function.appendArgument(callFrameId); 100 RefPtr<JSONValue> resultValue; 101 makeCall(function, &resultValue); 102 if (resultValue) { 103 if (resultValue->type() == JSONValue::TypeString) { 104 resultValue->asString(errorString); 105 return; 106 } 107 if (resultValue->type() == JSONValue::TypeObject) { 108 *result = resultValue->asObject(); 109 return; 110 } 111 } 112 *errorString = "Internal error"; 113 } 114 115 void InjectedScript::getStepInPositions(ErrorString* errorString, const ScriptValue& callFrames, const String& callFrameId, RefPtr<Array<TypeBuilder::Debugger::Location> >& positions) 116 { 117 ScriptFunctionCall function(injectedScriptObject(), "getStepInPositions"); 118 function.appendArgument(callFrames); 119 function.appendArgument(callFrameId); 120 RefPtr<JSONValue> resultValue; 121 makeCall(function, &resultValue); 122 if (resultValue) { 123 if (resultValue->type() == JSONValue::TypeString) { 124 resultValue->asString(errorString); 125 return; 126 } 127 if (resultValue->type() == JSONValue::TypeArray) { 128 positions = Array<TypeBuilder::Debugger::Location>::runtimeCast(resultValue); 129 return; 130 } 131 } 132 *errorString = "Internal error"; 133 } 134 135 void InjectedScript::setVariableValue(ErrorString* errorString, const ScriptValue& callFrames, const String* callFrameIdOpt, const String* functionObjectIdOpt, int scopeNumber, const String& variableName, const String& newValueStr) 136 { 137 ScriptFunctionCall function(injectedScriptObject(), "setVariableValue"); 138 if (callFrameIdOpt) { 139 function.appendArgument(callFrames); 140 function.appendArgument(*callFrameIdOpt); 141 } else { 142 function.appendArgument(false); 143 function.appendArgument(false); 144 } 145 if (functionObjectIdOpt) 146 function.appendArgument(*functionObjectIdOpt); 147 else 148 function.appendArgument(false); 149 function.appendArgument(scopeNumber); 150 function.appendArgument(variableName); 151 function.appendArgument(newValueStr); 152 RefPtr<JSONValue> resultValue; 153 makeCall(function, &resultValue); 154 if (!resultValue) { 155 *errorString = "Internal error"; 156 return; 157 } 158 if (resultValue->type() == JSONValue::TypeString) { 159 resultValue->asString(errorString); 160 return; 161 } 162 // Normal return. 163 } 164 165 void InjectedScript::getFunctionDetails(ErrorString* errorString, const String& functionId, RefPtr<FunctionDetails>* result) 166 { 167 ScriptFunctionCall function(injectedScriptObject(), "getFunctionDetails"); 168 function.appendArgument(functionId); 169 RefPtr<JSONValue> resultValue; 170 makeCall(function, &resultValue); 171 if (!resultValue || resultValue->type() != JSONValue::TypeObject) { 172 if (!resultValue->asString(errorString)) 173 *errorString = "Internal error"; 174 return; 175 } 176 *result = FunctionDetails::runtimeCast(resultValue); 177 } 178 179 void InjectedScript::getProperties(ErrorString* errorString, const String& objectId, bool ownProperties, bool accessorPropertiesOnly, RefPtr<Array<PropertyDescriptor> >* properties) 180 { 181 ScriptFunctionCall function(injectedScriptObject(), "getProperties"); 182 function.appendArgument(objectId); 183 function.appendArgument(ownProperties); 184 function.appendArgument(accessorPropertiesOnly); 185 186 RefPtr<JSONValue> result; 187 makeCall(function, &result); 188 if (!result || result->type() != JSONValue::TypeArray) { 189 *errorString = "Internal error"; 190 return; 191 } 192 *properties = Array<PropertyDescriptor>::runtimeCast(result); 193 } 194 195 void InjectedScript::getInternalProperties(ErrorString* errorString, const String& objectId, RefPtr<Array<InternalPropertyDescriptor> >* properties) 196 { 197 ScriptFunctionCall function(injectedScriptObject(), "getInternalProperties"); 198 function.appendArgument(objectId); 199 200 RefPtr<JSONValue> result; 201 makeCall(function, &result); 202 if (!result || result->type() != JSONValue::TypeArray) { 203 *errorString = "Internal error"; 204 return; 205 } 206 RefPtr<Array<InternalPropertyDescriptor> > array = Array<InternalPropertyDescriptor>::runtimeCast(result); 207 if (array->length() > 0) 208 *properties = array; 209 } 210 211 Node* InjectedScript::nodeForObjectId(const String& objectId) 212 { 213 if (hasNoValue() || !canAccessInspectedWindow()) 214 return 0; 215 216 ScriptFunctionCall function(injectedScriptObject(), "nodeForObjectId"); 217 function.appendArgument(objectId); 218 219 bool hadException = false; 220 ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException); 221 ASSERT(!hadException); 222 223 return InjectedScriptHost::scriptValueAsNode(resultValue); 224 } 225 226 void InjectedScript::releaseObject(const String& objectId) 227 { 228 ScriptFunctionCall function(injectedScriptObject(), "releaseObject"); 229 function.appendArgument(objectId); 230 RefPtr<JSONValue> result; 231 makeCall(function, &result); 232 } 233 234 PassRefPtr<Array<CallFrame> > InjectedScript::wrapCallFrames(const ScriptValue& callFrames) 235 { 236 ASSERT(!hasNoValue()); 237 ScriptFunctionCall function(injectedScriptObject(), "wrapCallFrames"); 238 function.appendArgument(callFrames); 239 bool hadException = false; 240 ScriptValue callFramesValue = callFunctionWithEvalEnabled(function, hadException); 241 ASSERT(!hadException); 242 RefPtr<JSONValue> result = callFramesValue.toJSONValue(scriptState()); 243 if (result->type() == JSONValue::TypeArray) 244 return Array<CallFrame>::runtimeCast(result); 245 return Array<CallFrame>::create(); 246 } 247 248 PassRefPtr<TypeBuilder::Runtime::RemoteObject> InjectedScript::wrapObject(const ScriptValue& value, const String& groupName, bool generatePreview) const 249 { 250 ASSERT(!hasNoValue()); 251 ScriptFunctionCall wrapFunction(injectedScriptObject(), "wrapObject"); 252 wrapFunction.appendArgument(value); 253 wrapFunction.appendArgument(groupName); 254 wrapFunction.appendArgument(canAccessInspectedWindow()); 255 wrapFunction.appendArgument(generatePreview); 256 bool hadException = false; 257 ScriptValue r = callFunctionWithEvalEnabled(wrapFunction, hadException); 258 if (hadException) 259 return 0; 260 RefPtr<JSONObject> rawResult = r.toJSONValue(scriptState())->asObject(); 261 return TypeBuilder::Runtime::RemoteObject::runtimeCast(rawResult); 262 } 263 264 PassRefPtr<TypeBuilder::Runtime::RemoteObject> InjectedScript::wrapTable(const ScriptValue& table, const ScriptValue& columns) const 265 { 266 ASSERT(!hasNoValue()); 267 ScriptFunctionCall wrapFunction(injectedScriptObject(), "wrapTable"); 268 wrapFunction.appendArgument(canAccessInspectedWindow()); 269 wrapFunction.appendArgument(table); 270 if (columns.hasNoValue()) 271 wrapFunction.appendArgument(false); 272 else 273 wrapFunction.appendArgument(columns); 274 bool hadException = false; 275 ScriptValue r = callFunctionWithEvalEnabled(wrapFunction, hadException); 276 if (hadException) 277 return 0; 278 RefPtr<JSONObject> rawResult = r.toJSONValue(scriptState())->asObject(); 279 return TypeBuilder::Runtime::RemoteObject::runtimeCast(rawResult); 280 } 281 282 PassRefPtr<TypeBuilder::Runtime::RemoteObject> InjectedScript::wrapNode(Node* node, const String& groupName) 283 { 284 return wrapObject(nodeAsScriptValue(node), groupName); 285 } 286 287 ScriptValue InjectedScript::findObjectById(const String& objectId) const 288 { 289 ASSERT(!hasNoValue()); 290 ScriptFunctionCall function(injectedScriptObject(), "findObjectById"); 291 function.appendArgument(objectId); 292 293 bool hadException = false; 294 ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException); 295 ASSERT(!hadException); 296 return resultValue; 297 } 298 299 ScriptValue InjectedScript::findCallFrameById(ErrorString* errorString, const ScriptValue& topCallFrame, const String& callFrameId) 300 { 301 ScriptFunctionCall function(injectedScriptObject(), "callFrameForId"); 302 function.appendArgument(topCallFrame); 303 function.appendArgument(callFrameId); 304 bool hadException = false; 305 ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException); 306 ASSERT(!hadException); 307 if (hadException || resultValue.hasNoValue() || !resultValue.isObject()) { 308 *errorString = "Internal error"; 309 return ScriptValue(); 310 } 311 return resultValue; 312 } 313 314 void InjectedScript::inspectNode(Node* node) 315 { 316 ASSERT(!hasNoValue()); 317 ScriptFunctionCall function(injectedScriptObject(), "inspectNode"); 318 function.appendArgument(nodeAsScriptValue(node)); 319 RefPtr<JSONValue> result; 320 makeCall(function, &result); 321 } 322 323 void InjectedScript::releaseObjectGroup(const String& objectGroup) 324 { 325 ASSERT(!hasNoValue()); 326 ScriptFunctionCall releaseFunction(injectedScriptObject(), "releaseObjectGroup"); 327 releaseFunction.appendArgument(objectGroup); 328 bool hadException = false; 329 callFunctionWithEvalEnabled(releaseFunction, hadException); 330 ASSERT(!hadException); 331 } 332 333 ScriptValue InjectedScript::nodeAsScriptValue(Node* node) 334 { 335 return InjectedScriptHost::nodeAsScriptValue(scriptState(), node); 336 } 337 338 } // namespace WebCore 339 340