1 /*
   2  * Copyright (C) 2013 Apple Inc. All rights reserved.
   3  * Copyright (C) 2012 Google Inc. All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions are
   7  * met:
   8  *
   9  *     * Redistributions of source code must retain the above copyright
  10  * notice, this list of conditions and the following disclaimer.
  11  *     * Redistributions in binary form must reproduce the above
  12  * copyright notice, this list of conditions and the following disclaimer
  13  * in the documentation and/or other materials provided with the
  14  * distribution.
  15  *     * Neither the name of Google Inc. nor the names of its
  16  * contributors may be used to endorse or promote products derived from
  17  * this software without specific prior written permission.
  18  *
  19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30  */
  31 
  32 #include "config.h"
  33 #include "InjectedScript.h"
  34 
  35 #include "InspectorValues.h"
  36 #include "JSCInlines.h"
  37 #include "ScriptFunctionCall.h"
  38 #include "ScriptObject.h"
  39 #include <wtf/text/WTFString.h>
  40 
  41 using Inspector::Protocol::Array;
  42 
  43 namespace Inspector {
  44 
  45 InjectedScript::InjectedScript()
  46     : InjectedScriptBase(ASCIILiteral("InjectedScript"))
  47 {
  48 }
  49 
  50 InjectedScript::InjectedScript(Deprecated::ScriptObject injectedScriptObject, InspectorEnvironment* environment)
  51     : InjectedScriptBase(ASCIILiteral("InjectedScript"), injectedScriptObject, environment)
  52 {
  53 }
  54 
  55 InjectedScript::~InjectedScript()
  56 {
  57 }
  58 
  59 void InjectedScript::evaluate(ErrorString& errorString, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr<Inspector::Protocol::Runtime::RemoteObject>* result, Inspector::Protocol::OptOutput<bool>* wasThrown, Inspector::Protocol::OptOutput<int>* savedResultIndex)
  60 {
  61     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("evaluate"), inspectorEnvironment()->functionCallHandler());
  62     function.appendArgument(expression);
  63     function.appendArgument(objectGroup);
  64     function.appendArgument(includeCommandLineAPI);
  65     function.appendArgument(returnByValue);
  66     function.appendArgument(generatePreview);
  67     function.appendArgument(saveResult);
  68     makeEvalCall(errorString, function, result, wasThrown, savedResultIndex);
  69 }
  70 
  71 void InjectedScript::callFunctionOn(ErrorString& errorString, const String& objectId, const String& expression, const String& arguments, bool returnByValue, bool generatePreview, RefPtr<Inspector::Protocol::Runtime::RemoteObject>* result, Inspector::Protocol::OptOutput<bool>* wasThrown)
  72 {
  73     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("callFunctionOn"), inspectorEnvironment()->functionCallHandler());
  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 Deprecated::ScriptValue& callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr<Inspector::Protocol::Runtime::RemoteObject>* result, Inspector::Protocol::OptOutput<bool>* wasThrown, Inspector::Protocol::OptOutput<int>* savedResultIndex)
  83 {
  84     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("evaluateOnCallFrame"), inspectorEnvironment()->functionCallHandler());
  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     function.appendArgument(saveResult);
  93     makeEvalCall(errorString, function, result, wasThrown, savedResultIndex);
  94 }
  95 
  96 void InjectedScript::getFunctionDetails(ErrorString& errorString, const String& functionId, RefPtr<Inspector::Protocol::Debugger::FunctionDetails>* result)
  97 {
  98     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("getFunctionDetails"), inspectorEnvironment()->functionCallHandler());
  99     function.appendArgument(functionId);
 100 
 101     RefPtr<InspectorValue> resultValue;
 102     makeCall(function, &resultValue);
 103     if (!resultValue || resultValue->type() != InspectorValue::Type::Object) {
 104         if (!resultValue->asString(errorString))
 105             errorString = ASCIILiteral("Internal error");
 106         return;
 107     }
 108 
 109     *result = BindingTraits<Inspector::Protocol::Debugger::FunctionDetails>::runtimeCast(WTF::move(resultValue));
 110 }
 111 
 112 void InjectedScript::getProperties(ErrorString& errorString, const String& objectId, bool ownProperties, bool generatePreview, RefPtr<Array<Inspector::Protocol::Runtime::PropertyDescriptor>>* properties)
 113 {
 114     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("getProperties"), inspectorEnvironment()->functionCallHandler());
 115     function.appendArgument(objectId);
 116     function.appendArgument(ownProperties);
 117     function.appendArgument(generatePreview);
 118 
 119     RefPtr<InspectorValue> result;
 120     makeCall(function, &result);
 121     if (!result || result->type() != InspectorValue::Type::Array) {
 122         errorString = ASCIILiteral("Internal error");
 123         return;
 124     }
 125 
 126     *properties = BindingTraits<Array<Inspector::Protocol::Runtime::PropertyDescriptor>>::runtimeCast(WTF::move(result));
 127 }
 128 
 129 void InjectedScript::getDisplayableProperties(ErrorString& errorString, const String& objectId, bool generatePreview, RefPtr<Array<Inspector::Protocol::Runtime::PropertyDescriptor>>* properties)
 130 {
 131     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("getDisplayableProperties"), inspectorEnvironment()->functionCallHandler());
 132     function.appendArgument(objectId);
 133     function.appendArgument(generatePreview);
 134 
 135     RefPtr<InspectorValue> result;
 136     makeCall(function, &result);
 137     if (!result || result->type() != InspectorValue::Type::Array) {
 138         errorString = ASCIILiteral("Internal error");
 139         return;
 140     }
 141 
 142     *properties = BindingTraits<Array<Inspector::Protocol::Runtime::PropertyDescriptor>>::runtimeCast(WTF::move(result));
 143 }
 144 
 145 void InjectedScript::getInternalProperties(ErrorString& errorString, const String& objectId, bool generatePreview, RefPtr<Array<Inspector::Protocol::Runtime::InternalPropertyDescriptor>>* properties)
 146 {
 147     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("getInternalProperties"), inspectorEnvironment()->functionCallHandler());
 148     function.appendArgument(objectId);
 149     function.appendArgument(generatePreview);
 150 
 151     RefPtr<InspectorValue> result;
 152     makeCall(function, &result);
 153     if (!result || result->type() != InspectorValue::Type::Array) {
 154         errorString = ASCIILiteral("Internal error");
 155         return;
 156     }
 157 
 158     auto array = BindingTraits<Array<Inspector::Protocol::Runtime::InternalPropertyDescriptor>>::runtimeCast(WTF::move(result));
 159     *properties = array->length() > 0 ? array : nullptr;
 160 }
 161 
 162 void InjectedScript::getCollectionEntries(ErrorString& errorString, const String& objectId, const String& objectGroup, int startIndex, int numberToFetch, RefPtr<Protocol::Array<Protocol::Runtime::CollectionEntry>>* entries)
 163 {
 164     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("getCollectionEntries"), inspectorEnvironment()->functionCallHandler());
 165     function.appendArgument(objectId);
 166     function.appendArgument(objectGroup);
 167     function.appendArgument(startIndex);
 168     function.appendArgument(numberToFetch);
 169 
 170     RefPtr<InspectorValue> result;
 171     makeCall(function, &result);
 172     if (!result || result->type() != InspectorValue::Type::Array) {
 173         errorString = ASCIILiteral("Internal error");
 174         return;
 175     }
 176 
 177     *entries = BindingTraits<Array<Protocol::Runtime::CollectionEntry>>::runtimeCast(WTF::move(result));
 178 }
 179 
 180 void InjectedScript::saveResult(ErrorString& errorString, const String& callArgumentJSON, Inspector::Protocol::OptOutput<int>* savedResultIndex)
 181 {
 182     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("saveResult"), inspectorEnvironment()->functionCallHandler());
 183     function.appendArgument(callArgumentJSON);
 184 
 185     RefPtr<InspectorValue> result;
 186     makeCall(function, &result);
 187     if (!result || result->type() != InspectorValue::Type::Integer) {
 188         errorString = ASCIILiteral("Internal error");
 189         return;
 190     }
 191 
 192     int savedResultIndexInt = 0;
 193     if (result->asInteger(savedResultIndexInt) && savedResultIndexInt > 0)
 194         *savedResultIndex = savedResultIndexInt;
 195 }
 196 
 197 Ref<Array<Inspector::Protocol::Debugger::CallFrame>> InjectedScript::wrapCallFrames(const Deprecated::ScriptValue& callFrames)
 198 {
 199     ASSERT(!hasNoValue());
 200     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("wrapCallFrames"), inspectorEnvironment()->functionCallHandler());
 201     function.appendArgument(callFrames);
 202 
 203     bool hadException = false;
 204     Deprecated::ScriptValue callFramesValue = callFunctionWithEvalEnabled(function, hadException);
 205     ASSERT(!hadException);
 206     RefPtr<InspectorValue> result = callFramesValue.toInspectorValue(scriptState());
 207     if (result->type() == InspectorValue::Type::Array)
 208         return BindingTraits<Array<Inspector::Protocol::Debugger::CallFrame>>::runtimeCast(WTF::move(result)).releaseNonNull();
 209 
 210     return Array<Inspector::Protocol::Debugger::CallFrame>::create();
 211 }
 212 
 213 RefPtr<Inspector::Protocol::Runtime::RemoteObject> InjectedScript::wrapObject(const Deprecated::ScriptValue& value, const String& groupName, bool generatePreview) const
 214 {
 215     ASSERT(!hasNoValue());
 216     Deprecated::ScriptFunctionCall wrapFunction(injectedScriptObject(), ASCIILiteral("wrapObject"), inspectorEnvironment()->functionCallHandler());
 217     wrapFunction.appendArgument(value);
 218     wrapFunction.appendArgument(groupName);
 219     wrapFunction.appendArgument(hasAccessToInspectedScriptState());
 220     wrapFunction.appendArgument(generatePreview);
 221 
 222     bool hadException = false;
 223     Deprecated::ScriptValue r = callFunctionWithEvalEnabled(wrapFunction, hadException);
 224     if (hadException)
 225         return nullptr;
 226 
 227     RefPtr<InspectorObject> resultObject;
 228     bool castSucceeded = r.toInspectorValue(scriptState())->asObject(resultObject);
 229     ASSERT_UNUSED(castSucceeded, castSucceeded);
 230 
 231     return BindingTraits<Inspector::Protocol::Runtime::RemoteObject>::runtimeCast(resultObject);
 232 }
 233 
 234 RefPtr<Inspector::Protocol::Runtime::RemoteObject> InjectedScript::wrapTable(const Deprecated::ScriptValue& table, const Deprecated::ScriptValue& columns) const
 235 {
 236     ASSERT(!hasNoValue());
 237     Deprecated::ScriptFunctionCall wrapFunction(injectedScriptObject(), ASCIILiteral("wrapTable"), inspectorEnvironment()->functionCallHandler());
 238     wrapFunction.appendArgument(hasAccessToInspectedScriptState());
 239     wrapFunction.appendArgument(table);
 240     if (columns.hasNoValue())
 241         wrapFunction.appendArgument(false);
 242     else
 243         wrapFunction.appendArgument(columns);
 244 
 245     bool hadException = false;
 246     Deprecated::ScriptValue r = callFunctionWithEvalEnabled(wrapFunction, hadException);
 247     if (hadException)
 248         return nullptr;
 249 
 250     RefPtr<InspectorObject> resultObject;
 251     bool castSucceeded = r.toInspectorValue(scriptState())->asObject(resultObject);
 252     ASSERT_UNUSED(castSucceeded, castSucceeded);
 253 
 254     return BindingTraits<Inspector::Protocol::Runtime::RemoteObject>::runtimeCast(resultObject);
 255 }
 256 
 257 void InjectedScript::setExceptionValue(const Deprecated::ScriptValue& value)
 258 {
 259     ASSERT(!hasNoValue());
 260     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("setExceptionValue"), inspectorEnvironment()->functionCallHandler());
 261     function.appendArgument(value);
 262     RefPtr<InspectorValue> result;
 263     makeCall(function, &result);
 264 }
 265 
 266 void InjectedScript::clearExceptionValue()
 267 {
 268     ASSERT(!hasNoValue());
 269     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("clearExceptionValue"), inspectorEnvironment()->functionCallHandler());
 270     RefPtr<InspectorValue> result;
 271     makeCall(function, &result);
 272 }
 273 
 274 Deprecated::ScriptValue InjectedScript::findObjectById(const String& objectId) const
 275 {
 276     ASSERT(!hasNoValue());
 277     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("findObjectById"), inspectorEnvironment()->functionCallHandler());
 278     function.appendArgument(objectId);
 279 
 280     bool hadException = false;
 281     Deprecated::ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException);
 282     ASSERT(!hadException);
 283 
 284     return resultValue;
 285 }
 286 
 287 void InjectedScript::inspectObject(Deprecated::ScriptValue value)
 288 {
 289     ASSERT(!hasNoValue());
 290     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("inspectObject"), inspectorEnvironment()->functionCallHandler());
 291     function.appendArgument(value);
 292     RefPtr<InspectorValue> result;
 293     makeCall(function, &result);
 294 }
 295 
 296 void InjectedScript::releaseObject(const String& objectId)
 297 {
 298     Deprecated::ScriptFunctionCall function(injectedScriptObject(), ASCIILiteral("releaseObject"), inspectorEnvironment()->functionCallHandler());
 299     function.appendArgument(objectId);
 300     RefPtr<InspectorValue> result;
 301     makeCall(function, &result);
 302 }
 303 
 304 void InjectedScript::releaseObjectGroup(const String& objectGroup)
 305 {
 306     ASSERT(!hasNoValue());
 307     // JDK-8164076
 308     if (hasNoValue())
 309         return;
 310 
 311     Deprecated::ScriptFunctionCall releaseFunction(injectedScriptObject(), ASCIILiteral("releaseObjectGroup"), inspectorEnvironment()->functionCallHandler());
 312     releaseFunction.appendArgument(objectGroup);
 313 
 314     bool hadException = false;
 315     callFunctionWithEvalEnabled(releaseFunction, hadException);
 316     ASSERT(!hadException);
 317 }
 318 
 319 } // namespace Inspector
 320