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(ScriptValue 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 Vector<ScriptValue>& asyncCallStacks, 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(asyncCallStacks); 87 function.appendArgument(callFrameId); 88 function.appendArgument(expression); 89 function.appendArgument(objectGroup); 90 function.appendArgument(includeCommandLineAPI); 91 function.appendArgument(returnByValue); 92 function.appendArgument(generatePreview); 93 makeEvalCall(errorString, function, result, wasThrown); 94 } 95 96 void InjectedScript::restartFrame(ErrorString* errorString, const ScriptValue& callFrames, const String& callFrameId, RefPtr<JSONObject>* result) 97 { 98 ScriptFunctionCall function(injectedScriptObject(), "restartFrame"); 99 function.appendArgument(callFrames); 100 function.appendArgument(callFrameId); 101 RefPtr<JSONValue> resultValue; 102 makeCall(function, &resultValue); 103 if (resultValue) { 104 if (resultValue->type() == JSONValue::TypeString) { 105 resultValue->asString(errorString); 106 return; 107 } 108 if (resultValue->type() == JSONValue::TypeObject) { 109 *result = resultValue->asObject(); 110 return; 111 } 112 } 113 *errorString = "Internal error"; 114 } 115 116 void InjectedScript::getStepInPositions(ErrorString* errorString, const ScriptValue& callFrames, const String& callFrameId, RefPtr<Array<TypeBuilder::Debugger::Location> >& positions) 117 { 118 ScriptFunctionCall function(injectedScriptObject(), "getStepInPositions"); 119 function.appendArgument(callFrames); 120 function.appendArgument(callFrameId); 121 RefPtr<JSONValue> resultValue; 122 makeCall(function, &resultValue); 123 if (resultValue) { 124 if (resultValue->type() == JSONValue::TypeString) { 125 resultValue->asString(errorString); 126 return; 127 } 128 if (resultValue->type() == JSONValue::TypeArray) { 129 positions = Array<TypeBuilder::Debugger::Location>::runtimeCast(resultValue); 130 return; 131 } 132 } 133 *errorString = "Internal error"; 134 } 135 136 void InjectedScript::setVariableValue(ErrorString* errorString, const ScriptValue& callFrames, const String* callFrameIdOpt, const String* functionObjectIdOpt, int scopeNumber, const String& variableName, const String& newValueStr) 137 { 138 ScriptFunctionCall function(injectedScriptObject(), "setVariableValue"); 139 if (callFrameIdOpt) { 140 function.appendArgument(callFrames); 141 function.appendArgument(*callFrameIdOpt); 142 } else { 143 function.appendArgument(false); 144 function.appendArgument(false); 145 } 146 if (functionObjectIdOpt) 147 function.appendArgument(*functionObjectIdOpt); 148 else 149 function.appendArgument(false); 150 function.appendArgument(scopeNumber); 151 function.appendArgument(variableName); 152 function.appendArgument(newValueStr); 153 RefPtr<JSONValue> resultValue; 154 makeCall(function, &resultValue); 155 if (!resultValue) { 156 *errorString = "Internal error"; 157 return; 158 } 159 if (resultValue->type() == JSONValue::TypeString) { 160 resultValue->asString(errorString); 161 return; 162 } 163 // Normal return. 164 } 165 166 void InjectedScript::getFunctionDetails(ErrorString* errorString, const String& functionId, RefPtr<FunctionDetails>* result) 167 { 168 ScriptFunctionCall function(injectedScriptObject(), "getFunctionDetails"); 169 function.appendArgument(functionId); 170 RefPtr<JSONValue> resultValue; 171 makeCall(function, &resultValue); 172 if (!resultValue || resultValue->type() != JSONValue::TypeObject) { 173 if (!resultValue->asString(errorString)) 174 *errorString = "Internal error"; 175 return; 176 } 177 *result = FunctionDetails::runtimeCast(resultValue); 178 } 179 180 void InjectedScript::getProperties(ErrorString* errorString, const String& objectId, bool ownProperties, bool accessorPropertiesOnly, RefPtr<Array<PropertyDescriptor> >* properties) 181 { 182 ScriptFunctionCall function(injectedScriptObject(), "getProperties"); 183 function.appendArgument(objectId); 184 function.appendArgument(ownProperties); 185 function.appendArgument(accessorPropertiesOnly); 186 187 RefPtr<JSONValue> result; 188 makeCall(function, &result); 189 if (!result || result->type() != JSONValue::TypeArray) { 190 *errorString = "Internal error"; 191 return; 192 } 193 *properties = Array<PropertyDescriptor>::runtimeCast(result); 194 } 195 196 void InjectedScript::getInternalProperties(ErrorString* errorString, const String& objectId, RefPtr<Array<InternalPropertyDescriptor> >* properties) 197 { 198 ScriptFunctionCall function(injectedScriptObject(), "getInternalProperties"); 199 function.appendArgument(objectId); 200 201 RefPtr<JSONValue> result; 202 makeCall(function, &result); 203 if (!result || result->type() != JSONValue::TypeArray) { 204 *errorString = "Internal error"; 205 return; 206 } 207 RefPtr<Array<InternalPropertyDescriptor> > array = Array<InternalPropertyDescriptor>::runtimeCast(result); 208 if (array->length() > 0) 209 *properties = array; 210 } 211 212 Node* InjectedScript::nodeForObjectId(const String& objectId) 213 { 214 if (isEmpty() || !canAccessInspectedWindow()) 215 return 0; 216 217 ScriptFunctionCall function(injectedScriptObject(), "nodeForObjectId"); 218 function.appendArgument(objectId); 219 220 bool hadException = false; 221 ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException); 222 ASSERT(!hadException); 223 224 return InjectedScriptHost::scriptValueAsNode(scriptState(), resultValue); 225 } 226 227 void InjectedScript::releaseObject(const String& objectId) 228 { 229 ScriptFunctionCall function(injectedScriptObject(), "releaseObject"); 230 function.appendArgument(objectId); 231 RefPtr<JSONValue> result; 232 makeCall(function, &result); 233 } 234 235 PassRefPtr<Array<CallFrame> > InjectedScript::wrapCallFrames(const ScriptValue& callFrames, int asyncOrdinal) 236 { 237 ASSERT(!isEmpty()); 238 ScriptFunctionCall function(injectedScriptObject(), "wrapCallFrames"); 239 function.appendArgument(callFrames); 240 function.appendArgument(asyncOrdinal); 241 bool hadException = false; 242 ScriptValue callFramesValue = callFunctionWithEvalEnabled(function, hadException); 243 ASSERT(!hadException); 244 RefPtr<JSONValue> result = callFramesValue.toJSONValue(scriptState()); 245 if (result && result->type() == JSONValue::TypeArray) 246 return Array<CallFrame>::runtimeCast(result); 247 return Array<CallFrame>::create(); 248 } 249 250 PassRefPtr<TypeBuilder::Runtime::RemoteObject> InjectedScript::wrapObject(const ScriptValue& value, const String& groupName, bool generatePreview) const 251 { 252 ASSERT(!isEmpty()); 253 ScriptFunctionCall wrapFunction(injectedScriptObject(), "wrapObject"); 254 wrapFunction.appendArgument(value); 255 wrapFunction.appendArgument(groupName); 256 wrapFunction.appendArgument(canAccessInspectedWindow()); 257 wrapFunction.appendArgument(generatePreview); 258 bool hadException = false; 259 ScriptValue r = callFunctionWithEvalEnabled(wrapFunction, hadException); 260 if (hadException) 261 return nullptr; 262 RefPtr<JSONObject> rawResult = r.toJSONValue(scriptState())->asObject(); 263 return TypeBuilder::Runtime::RemoteObject::runtimeCast(rawResult); 264 } 265 266 PassRefPtr<TypeBuilder::Runtime::RemoteObject> InjectedScript::wrapTable(const ScriptValue& table, const ScriptValue& columns) const 267 { 268 ASSERT(!isEmpty()); 269 ScriptFunctionCall wrapFunction(injectedScriptObject(), "wrapTable"); 270 wrapFunction.appendArgument(canAccessInspectedWindow()); 271 wrapFunction.appendArgument(table); 272 if (columns.isEmpty()) 273 wrapFunction.appendArgument(false); 274 else 275 wrapFunction.appendArgument(columns); 276 bool hadException = false; 277 ScriptValue r = callFunctionWithEvalEnabled(wrapFunction, hadException); 278 if (hadException) 279 return nullptr; 280 RefPtr<JSONObject> rawResult = r.toJSONValue(scriptState())->asObject(); 281 return TypeBuilder::Runtime::RemoteObject::runtimeCast(rawResult); 282 } 283 284 PassRefPtr<TypeBuilder::Runtime::RemoteObject> InjectedScript::wrapNode(Node* node, const String& groupName) 285 { 286 return wrapObject(nodeAsScriptValue(node), groupName); 287 } 288 289 ScriptValue InjectedScript::findObjectById(const String& objectId) const 290 { 291 ASSERT(!isEmpty()); 292 ScriptFunctionCall function(injectedScriptObject(), "findObjectById"); 293 function.appendArgument(objectId); 294 295 bool hadException = false; 296 ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException); 297 ASSERT(!hadException); 298 return resultValue; 299 } 300 301 void InjectedScript::inspectNode(Node* node) 302 { 303 ASSERT(!isEmpty()); 304 ScriptFunctionCall function(injectedScriptObject(), "inspectNode"); 305 function.appendArgument(nodeAsScriptValue(node)); 306 RefPtr<JSONValue> result; 307 makeCall(function, &result); 308 } 309 310 void InjectedScript::releaseObjectGroup(const String& objectGroup) 311 { 312 ASSERT(!isEmpty()); 313 ScriptFunctionCall releaseFunction(injectedScriptObject(), "releaseObjectGroup"); 314 releaseFunction.appendArgument(objectGroup); 315 bool hadException = false; 316 callFunctionWithEvalEnabled(releaseFunction, hadException); 317 ASSERT(!hadException); 318 } 319 320 ScriptValue InjectedScript::nodeAsScriptValue(Node* node) 321 { 322 return InjectedScriptHost::nodeAsScriptValue(scriptState(), node); 323 } 324 325 } // namespace WebCore 326 327