Home | History | Annotate | Download | only in inspector
      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 "core/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 void InjectedScript::inspectNode(Node* node)
    300 {
    301     ASSERT(!hasNoValue());
    302     ScriptFunctionCall function(injectedScriptObject(), "inspectNode");
    303     function.appendArgument(nodeAsScriptValue(node));
    304     RefPtr<JSONValue> result;
    305     makeCall(function, &result);
    306 }
    307 
    308 void InjectedScript::releaseObjectGroup(const String& objectGroup)
    309 {
    310     ASSERT(!hasNoValue());
    311     ScriptFunctionCall releaseFunction(injectedScriptObject(), "releaseObjectGroup");
    312     releaseFunction.appendArgument(objectGroup);
    313     bool hadException = false;
    314     callFunctionWithEvalEnabled(releaseFunction, hadException);
    315     ASSERT(!hadException);
    316 }
    317 
    318 ScriptValue InjectedScript::nodeAsScriptValue(Node* node)
    319 {
    320     return InjectedScriptHost::nodeAsScriptValue(scriptState(), node);
    321 }
    322 
    323 } // namespace WebCore
    324 
    325