1 /* 2 * Copyright (C) 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 "core/inspector/InspectorRuntimeAgent.h" 33 34 #include "bindings/core/v8/DOMWrapperWorld.h" 35 #include "bindings/core/v8/ScriptDebugServer.h" 36 #include "bindings/core/v8/ScriptState.h" 37 #include "core/inspector/InjectedScript.h" 38 #include "core/inspector/InjectedScriptManager.h" 39 #include "core/inspector/InspectorState.h" 40 #include "platform/JSONValues.h" 41 42 using blink::TypeBuilder::Runtime::ExecutionContextDescription; 43 44 namespace blink { 45 46 namespace InspectorRuntimeAgentState { 47 static const char runtimeEnabled[] = "runtimeEnabled"; 48 }; 49 50 InspectorRuntimeAgent::InspectorRuntimeAgent(InjectedScriptManager* injectedScriptManager, ScriptDebugServer* scriptDebugServer) 51 : InspectorBaseAgent<InspectorRuntimeAgent>("Runtime") 52 , m_enabled(false) 53 , m_frontend(0) 54 , m_injectedScriptManager(injectedScriptManager) 55 , m_scriptDebugServer(scriptDebugServer) 56 { 57 } 58 59 InspectorRuntimeAgent::~InspectorRuntimeAgent() 60 { 61 } 62 63 void InspectorRuntimeAgent::trace(Visitor* visitor) 64 { 65 visitor->trace(m_injectedScriptManager); 66 InspectorBaseAgent::trace(visitor); 67 } 68 69 static ScriptDebugServer::PauseOnExceptionsState setPauseOnExceptionsState(ScriptDebugServer* scriptDebugServer, ScriptDebugServer::PauseOnExceptionsState newState) 70 { 71 ASSERT(scriptDebugServer); 72 ScriptDebugServer::PauseOnExceptionsState presentState = scriptDebugServer->pauseOnExceptionsState(); 73 if (presentState != newState) 74 scriptDebugServer->setPauseOnExceptionsState(newState); 75 return presentState; 76 } 77 78 void InspectorRuntimeAgent::evaluate(ErrorString* errorString, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const doNotPauseOnExceptionsAndMuteConsole, const int* executionContextId, const bool* const returnByValue, const bool* generatePreview, RefPtr<TypeBuilder::Runtime::RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown, RefPtr<TypeBuilder::Debugger::ExceptionDetails>& exceptionDetails) 79 { 80 InjectedScript injectedScript = injectedScriptForEval(errorString, executionContextId); 81 if (injectedScript.isEmpty()) 82 return; 83 ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = ScriptDebugServer::DontPauseOnExceptions; 84 if (asBool(doNotPauseOnExceptionsAndMuteConsole)) 85 previousPauseOnExceptionsState = setPauseOnExceptionsState(m_scriptDebugServer, ScriptDebugServer::DontPauseOnExceptions); 86 if (asBool(doNotPauseOnExceptionsAndMuteConsole)) 87 muteConsole(); 88 89 injectedScript.evaluate(errorString, expression, objectGroup ? *objectGroup : "", asBool(includeCommandLineAPI), asBool(returnByValue), asBool(generatePreview), &result, wasThrown, &exceptionDetails); 90 91 if (asBool(doNotPauseOnExceptionsAndMuteConsole)) { 92 unmuteConsole(); 93 setPauseOnExceptionsState(m_scriptDebugServer, previousPauseOnExceptionsState); 94 } 95 } 96 97 void InspectorRuntimeAgent::callFunctionOn(ErrorString* errorString, const String& objectId, const String& expression, const RefPtr<JSONArray>* const optionalArguments, const bool* const doNotPauseOnExceptionsAndMuteConsole, const bool* const returnByValue, const bool* generatePreview, RefPtr<TypeBuilder::Runtime::RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown) 98 { 99 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId); 100 if (injectedScript.isEmpty()) { 101 *errorString = "Inspected frame has gone"; 102 return; 103 } 104 String arguments; 105 if (optionalArguments) 106 arguments = (*optionalArguments)->toJSONString(); 107 108 ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = ScriptDebugServer::DontPauseOnExceptions; 109 if (asBool(doNotPauseOnExceptionsAndMuteConsole)) 110 previousPauseOnExceptionsState = setPauseOnExceptionsState(m_scriptDebugServer, ScriptDebugServer::DontPauseOnExceptions); 111 if (asBool(doNotPauseOnExceptionsAndMuteConsole)) 112 muteConsole(); 113 114 injectedScript.callFunctionOn(errorString, objectId, expression, arguments, asBool(returnByValue), asBool(generatePreview), &result, wasThrown); 115 116 if (asBool(doNotPauseOnExceptionsAndMuteConsole)) { 117 unmuteConsole(); 118 setPauseOnExceptionsState(m_scriptDebugServer, previousPauseOnExceptionsState); 119 } 120 } 121 122 void InspectorRuntimeAgent::getProperties(ErrorString* errorString, const String& objectId, const bool* ownProperties, const bool* accessorPropertiesOnly, RefPtr<TypeBuilder::Array<TypeBuilder::Runtime::PropertyDescriptor> >& result, RefPtr<TypeBuilder::Array<TypeBuilder::Runtime::InternalPropertyDescriptor> >& internalProperties) 123 { 124 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId); 125 if (injectedScript.isEmpty()) { 126 *errorString = "Inspected frame has gone"; 127 return; 128 } 129 130 ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = setPauseOnExceptionsState(m_scriptDebugServer, ScriptDebugServer::DontPauseOnExceptions); 131 muteConsole(); 132 133 injectedScript.getProperties(errorString, objectId, asBool(ownProperties), asBool(accessorPropertiesOnly), &result); 134 135 if (!asBool(accessorPropertiesOnly)) 136 injectedScript.getInternalProperties(errorString, objectId, &internalProperties); 137 138 unmuteConsole(); 139 setPauseOnExceptionsState(m_scriptDebugServer, previousPauseOnExceptionsState); 140 } 141 142 void InspectorRuntimeAgent::releaseObject(ErrorString*, const String& objectId) 143 { 144 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId); 145 if (injectedScript.isEmpty()) 146 return; 147 bool pausingOnNextStatement = m_scriptDebugServer->pausingOnNextStatement(); 148 if (pausingOnNextStatement) 149 m_scriptDebugServer->setPauseOnNextStatement(false); 150 injectedScript.releaseObject(objectId); 151 if (pausingOnNextStatement) 152 m_scriptDebugServer->setPauseOnNextStatement(true); 153 } 154 155 void InspectorRuntimeAgent::releaseObjectGroup(ErrorString*, const String& objectGroup) 156 { 157 bool pausingOnNextStatement = m_scriptDebugServer->pausingOnNextStatement(); 158 if (pausingOnNextStatement) 159 m_scriptDebugServer->setPauseOnNextStatement(false); 160 m_injectedScriptManager->releaseObjectGroup(objectGroup); 161 if (pausingOnNextStatement) 162 m_scriptDebugServer->setPauseOnNextStatement(true); 163 } 164 165 void InspectorRuntimeAgent::run(ErrorString*) 166 { 167 } 168 169 void InspectorRuntimeAgent::isRunRequired(ErrorString*, bool* out_result) 170 { 171 *out_result = false; 172 } 173 174 void InspectorRuntimeAgent::setFrontend(InspectorFrontend* frontend) 175 { 176 m_frontend = frontend->runtime(); 177 } 178 179 void InspectorRuntimeAgent::clearFrontend() 180 { 181 m_frontend = 0; 182 String errorString; 183 disable(&errorString); 184 } 185 186 void InspectorRuntimeAgent::restore() 187 { 188 if (m_state->getBoolean(InspectorRuntimeAgentState::runtimeEnabled)) { 189 m_scriptStateToId.clear(); 190 m_frontend->executionContextsCleared(); 191 String error; 192 enable(&error); 193 } 194 } 195 196 void InspectorRuntimeAgent::enable(ErrorString* errorString) 197 { 198 if (m_enabled) 199 return; 200 201 m_enabled = true; 202 m_state->setBoolean(InspectorRuntimeAgentState::runtimeEnabled, true); 203 } 204 205 void InspectorRuntimeAgent::disable(ErrorString* errorString) 206 { 207 if (!m_enabled) 208 return; 209 210 m_scriptStateToId.clear(); 211 m_enabled = false; 212 m_state->setBoolean(InspectorRuntimeAgentState::runtimeEnabled, false); 213 } 214 215 void InspectorRuntimeAgent::addExecutionContextToFrontend(ScriptState* scriptState, bool isPageContext, const String& origin, const String& frameId) 216 { 217 int executionContextId = injectedScriptManager()->injectedScriptIdFor(scriptState); 218 m_scriptStateToId.set(scriptState, executionContextId); 219 DOMWrapperWorld& world = scriptState->world(); 220 String humanReadableName = world.isIsolatedWorld() ? world.isolatedWorldHumanReadableName() : ""; 221 m_frontend->executionContextCreated(ExecutionContextDescription::create() 222 .setId(executionContextId) 223 .setIsPageContext(isPageContext) 224 .setName(humanReadableName) 225 .setOrigin(origin) 226 .setFrameId(frameId) 227 .release()); 228 } 229 230 } // namespace blink 231 232