| OLD | NEW |
| (Empty) |
| 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 "src/inspector/InjectedScript.h" | |
| 32 | |
| 33 #include "src/inspector/InjectedScriptNative.h" | |
| 34 #include "src/inspector/InjectedScriptSource.h" | |
| 35 #include "src/inspector/InspectedContext.h" | |
| 36 #include "src/inspector/RemoteObjectId.h" | |
| 37 #include "src/inspector/StringUtil.h" | |
| 38 #include "src/inspector/V8Console.h" | |
| 39 #include "src/inspector/V8FunctionCall.h" | |
| 40 #include "src/inspector/V8InjectedScriptHost.h" | |
| 41 #include "src/inspector/V8InspectorImpl.h" | |
| 42 #include "src/inspector/V8InspectorSessionImpl.h" | |
| 43 #include "src/inspector/V8StackTraceImpl.h" | |
| 44 #include "src/inspector/V8ValueCopier.h" | |
| 45 #include "src/inspector/protocol/Protocol.h" | |
| 46 | |
| 47 #include "include/v8-inspector.h" | |
| 48 | |
| 49 namespace v8_inspector { | |
| 50 | |
| 51 using protocol::Array; | |
| 52 using protocol::Runtime::PropertyDescriptor; | |
| 53 using protocol::Runtime::InternalPropertyDescriptor; | |
| 54 using protocol::Runtime::RemoteObject; | |
| 55 using protocol::Maybe; | |
| 56 | |
| 57 static bool hasInternalError(ErrorString* errorString, bool hasError) { | |
| 58 if (hasError) *errorString = "Internal error"; | |
| 59 return hasError; | |
| 60 } | |
| 61 | |
| 62 std::unique_ptr<InjectedScript> InjectedScript::create( | |
| 63 InspectedContext* inspectedContext) { | |
| 64 v8::Isolate* isolate = inspectedContext->isolate(); | |
| 65 v8::HandleScope handles(isolate); | |
| 66 v8::Local<v8::Context> context = inspectedContext->context(); | |
| 67 v8::Context::Scope scope(context); | |
| 68 | |
| 69 std::unique_ptr<InjectedScriptNative> injectedScriptNative( | |
| 70 new InjectedScriptNative(isolate)); | |
| 71 v8::Local<v8::Object> scriptHostWrapper = | |
| 72 V8InjectedScriptHost::create(context, inspectedContext->inspector()); | |
| 73 injectedScriptNative->setOnInjectedScriptHost(scriptHostWrapper); | |
| 74 | |
| 75 // Inject javascript into the context. The compiled script is supposed to | |
| 76 // evaluate into | |
| 77 // a single anonymous function(it's anonymous to avoid cluttering the global | |
| 78 // object with | |
| 79 // inspector's stuff) the function is called a few lines below with | |
| 80 // InjectedScriptHost wrapper, | |
| 81 // injected script id and explicit reference to the inspected global object. | |
| 82 // The function is expected | |
| 83 // to create and configure InjectedScript instance that is going to be used by | |
| 84 // the inspector. | |
| 85 String16 injectedScriptSource( | |
| 86 reinterpret_cast<const char*>(InjectedScriptSource_js), | |
| 87 sizeof(InjectedScriptSource_js)); | |
| 88 v8::Local<v8::Value> value; | |
| 89 if (!inspectedContext->inspector() | |
| 90 ->compileAndRunInternalScript( | |
| 91 context, toV8String(isolate, injectedScriptSource)) | |
| 92 .ToLocal(&value)) | |
| 93 return nullptr; | |
| 94 DCHECK(value->IsFunction()); | |
| 95 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(value); | |
| 96 v8::Local<v8::Object> windowGlobal = context->Global(); | |
| 97 v8::Local<v8::Value> info[] = { | |
| 98 scriptHostWrapper, windowGlobal, | |
| 99 v8::Number::New(isolate, inspectedContext->contextId())}; | |
| 100 v8::MicrotasksScope microtasksScope(isolate, | |
| 101 v8::MicrotasksScope::kDoNotRunMicrotasks); | |
| 102 v8::Local<v8::Value> injectedScriptValue; | |
| 103 if (!function->Call(context, windowGlobal, arraysize(info), info) | |
| 104 .ToLocal(&injectedScriptValue)) | |
| 105 return nullptr; | |
| 106 if (!injectedScriptValue->IsObject()) return nullptr; | |
| 107 return wrapUnique(new InjectedScript(inspectedContext, | |
| 108 injectedScriptValue.As<v8::Object>(), | |
| 109 std::move(injectedScriptNative))); | |
| 110 } | |
| 111 | |
| 112 InjectedScript::InjectedScript( | |
| 113 InspectedContext* context, v8::Local<v8::Object> object, | |
| 114 std::unique_ptr<InjectedScriptNative> injectedScriptNative) | |
| 115 : m_context(context), | |
| 116 m_value(context->isolate(), object), | |
| 117 m_native(std::move(injectedScriptNative)) {} | |
| 118 | |
| 119 InjectedScript::~InjectedScript() {} | |
| 120 | |
| 121 void InjectedScript::getProperties( | |
| 122 ErrorString* errorString, v8::Local<v8::Object> object, | |
| 123 const String16& groupName, bool ownProperties, bool accessorPropertiesOnly, | |
| 124 bool generatePreview, | |
| 125 std::unique_ptr<Array<PropertyDescriptor>>* properties, | |
| 126 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { | |
| 127 v8::HandleScope handles(m_context->isolate()); | |
| 128 v8::Local<v8::Context> context = m_context->context(); | |
| 129 V8FunctionCall function(m_context->inspector(), m_context->context(), | |
| 130 v8Value(), "getProperties"); | |
| 131 function.appendArgument(object); | |
| 132 function.appendArgument(groupName); | |
| 133 function.appendArgument(ownProperties); | |
| 134 function.appendArgument(accessorPropertiesOnly); | |
| 135 function.appendArgument(generatePreview); | |
| 136 | |
| 137 v8::TryCatch tryCatch(m_context->isolate()); | |
| 138 v8::Local<v8::Value> resultValue = function.callWithoutExceptionHandling(); | |
| 139 if (tryCatch.HasCaught()) { | |
| 140 *exceptionDetails = createExceptionDetails(errorString, tryCatch, groupName, | |
| 141 generatePreview); | |
| 142 // FIXME: make properties optional | |
| 143 *properties = Array<PropertyDescriptor>::create(); | |
| 144 return; | |
| 145 } | |
| 146 | |
| 147 std::unique_ptr<protocol::Value> protocolValue = | |
| 148 toProtocolValue(context, resultValue); | |
| 149 if (hasInternalError(errorString, !protocolValue)) return; | |
| 150 protocol::ErrorSupport errors(errorString); | |
| 151 std::unique_ptr<Array<PropertyDescriptor>> result = | |
| 152 Array<PropertyDescriptor>::parse(protocolValue.get(), &errors); | |
| 153 if (!hasInternalError(errorString, errors.hasErrors())) | |
| 154 *properties = std::move(result); | |
| 155 } | |
| 156 | |
| 157 void InjectedScript::releaseObject(const String16& objectId) { | |
| 158 std::unique_ptr<protocol::Value> parsedObjectId = | |
| 159 protocol::parseJSON(objectId); | |
| 160 if (!parsedObjectId) return; | |
| 161 protocol::DictionaryValue* object = | |
| 162 protocol::DictionaryValue::cast(parsedObjectId.get()); | |
| 163 if (!object) return; | |
| 164 int boundId = 0; | |
| 165 if (!object->getInteger("id", &boundId)) return; | |
| 166 m_native->unbind(boundId); | |
| 167 } | |
| 168 | |
| 169 std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapObject( | |
| 170 ErrorString* errorString, v8::Local<v8::Value> value, | |
| 171 const String16& groupName, bool forceValueType, | |
| 172 bool generatePreview) const { | |
| 173 v8::HandleScope handles(m_context->isolate()); | |
| 174 v8::Local<v8::Value> wrappedObject; | |
| 175 v8::Local<v8::Context> context = m_context->context(); | |
| 176 if (!wrapValue(errorString, value, groupName, forceValueType, generatePreview) | |
| 177 .ToLocal(&wrappedObject)) | |
| 178 return nullptr; | |
| 179 protocol::ErrorSupport errors; | |
| 180 std::unique_ptr<protocol::Runtime::RemoteObject> remoteObject = | |
| 181 protocol::Runtime::RemoteObject::parse( | |
| 182 toProtocolValue(context, wrappedObject).get(), &errors); | |
| 183 if (!remoteObject) *errorString = "Object has too long reference chain"; | |
| 184 return remoteObject; | |
| 185 } | |
| 186 | |
| 187 bool InjectedScript::wrapObjectProperty(ErrorString* errorString, | |
| 188 v8::Local<v8::Object> object, | |
| 189 v8::Local<v8::Name> key, | |
| 190 const String16& groupName, | |
| 191 bool forceValueType, | |
| 192 bool generatePreview) const { | |
| 193 v8::Local<v8::Value> property; | |
| 194 v8::Local<v8::Context> context = m_context->context(); | |
| 195 if (hasInternalError(errorString, | |
| 196 !object->Get(context, key).ToLocal(&property))) | |
| 197 return false; | |
| 198 v8::Local<v8::Value> wrappedProperty; | |
| 199 if (!wrapValue(errorString, property, groupName, forceValueType, | |
| 200 generatePreview) | |
| 201 .ToLocal(&wrappedProperty)) | |
| 202 return false; | |
| 203 v8::Maybe<bool> success = | |
| 204 createDataProperty(context, object, key, wrappedProperty); | |
| 205 if (hasInternalError(errorString, success.IsNothing() || !success.FromJust())) | |
| 206 return false; | |
| 207 return true; | |
| 208 } | |
| 209 | |
| 210 bool InjectedScript::wrapPropertyInArray(ErrorString* errorString, | |
| 211 v8::Local<v8::Array> array, | |
| 212 v8::Local<v8::String> property, | |
| 213 const String16& groupName, | |
| 214 bool forceValueType, | |
| 215 bool generatePreview) const { | |
| 216 V8FunctionCall function(m_context->inspector(), m_context->context(), | |
| 217 v8Value(), "wrapPropertyInArray"); | |
| 218 function.appendArgument(array); | |
| 219 function.appendArgument(property); | |
| 220 function.appendArgument(groupName); | |
| 221 function.appendArgument(forceValueType); | |
| 222 function.appendArgument(generatePreview); | |
| 223 bool hadException = false; | |
| 224 function.call(hadException); | |
| 225 return !hasInternalError(errorString, hadException); | |
| 226 } | |
| 227 | |
| 228 bool InjectedScript::wrapObjectsInArray(ErrorString* errorString, | |
| 229 v8::Local<v8::Array> array, | |
| 230 const String16& groupName, | |
| 231 bool forceValueType, | |
| 232 bool generatePreview) const { | |
| 233 V8FunctionCall function(m_context->inspector(), m_context->context(), | |
| 234 v8Value(), "wrapObjectsInArray"); | |
| 235 function.appendArgument(array); | |
| 236 function.appendArgument(groupName); | |
| 237 function.appendArgument(forceValueType); | |
| 238 function.appendArgument(generatePreview); | |
| 239 bool hadException = false; | |
| 240 function.call(hadException); | |
| 241 return !hasInternalError(errorString, hadException); | |
| 242 } | |
| 243 | |
| 244 v8::MaybeLocal<v8::Value> InjectedScript::wrapValue( | |
| 245 ErrorString* errorString, v8::Local<v8::Value> value, | |
| 246 const String16& groupName, bool forceValueType, | |
| 247 bool generatePreview) const { | |
| 248 V8FunctionCall function(m_context->inspector(), m_context->context(), | |
| 249 v8Value(), "wrapObject"); | |
| 250 function.appendArgument(value); | |
| 251 function.appendArgument(groupName); | |
| 252 function.appendArgument(forceValueType); | |
| 253 function.appendArgument(generatePreview); | |
| 254 bool hadException = false; | |
| 255 v8::Local<v8::Value> r = function.call(hadException); | |
| 256 if (hasInternalError(errorString, hadException || r.IsEmpty())) | |
| 257 return v8::MaybeLocal<v8::Value>(); | |
| 258 return r; | |
| 259 } | |
| 260 | |
| 261 std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapTable( | |
| 262 v8::Local<v8::Value> table, v8::Local<v8::Value> columns) const { | |
| 263 v8::HandleScope handles(m_context->isolate()); | |
| 264 v8::Local<v8::Context> context = m_context->context(); | |
| 265 V8FunctionCall function(m_context->inspector(), context, v8Value(), | |
| 266 "wrapTable"); | |
| 267 function.appendArgument(table); | |
| 268 if (columns.IsEmpty()) | |
| 269 function.appendArgument(false); | |
| 270 else | |
| 271 function.appendArgument(columns); | |
| 272 bool hadException = false; | |
| 273 v8::Local<v8::Value> r = function.call(hadException); | |
| 274 if (hadException) return nullptr; | |
| 275 protocol::ErrorSupport errors; | |
| 276 return protocol::Runtime::RemoteObject::parse( | |
| 277 toProtocolValue(context, r).get(), &errors); | |
| 278 } | |
| 279 | |
| 280 bool InjectedScript::findObject(ErrorString* errorString, | |
| 281 const RemoteObjectId& objectId, | |
| 282 v8::Local<v8::Value>* outObject) const { | |
| 283 *outObject = m_native->objectForId(objectId.id()); | |
| 284 if (outObject->IsEmpty()) | |
| 285 *errorString = "Could not find object with given id"; | |
| 286 return !outObject->IsEmpty(); | |
| 287 } | |
| 288 | |
| 289 String16 InjectedScript::objectGroupName(const RemoteObjectId& objectId) const { | |
| 290 return m_native->groupName(objectId.id()); | |
| 291 } | |
| 292 | |
| 293 void InjectedScript::releaseObjectGroup(const String16& objectGroup) { | |
| 294 m_native->releaseObjectGroup(objectGroup); | |
| 295 if (objectGroup == "console") m_lastEvaluationResult.Reset(); | |
| 296 } | |
| 297 | |
| 298 void InjectedScript::setCustomObjectFormatterEnabled(bool enabled) { | |
| 299 v8::HandleScope handles(m_context->isolate()); | |
| 300 V8FunctionCall function(m_context->inspector(), m_context->context(), | |
| 301 v8Value(), "setCustomObjectFormatterEnabled"); | |
| 302 function.appendArgument(enabled); | |
| 303 bool hadException = false; | |
| 304 function.call(hadException); | |
| 305 DCHECK(!hadException); | |
| 306 } | |
| 307 | |
| 308 v8::Local<v8::Value> InjectedScript::v8Value() const { | |
| 309 return m_value.Get(m_context->isolate()); | |
| 310 } | |
| 311 | |
| 312 v8::Local<v8::Value> InjectedScript::lastEvaluationResult() const { | |
| 313 if (m_lastEvaluationResult.IsEmpty()) | |
| 314 return v8::Undefined(m_context->isolate()); | |
| 315 return m_lastEvaluationResult.Get(m_context->isolate()); | |
| 316 } | |
| 317 | |
| 318 v8::MaybeLocal<v8::Value> InjectedScript::resolveCallArgument( | |
| 319 ErrorString* errorString, protocol::Runtime::CallArgument* callArgument) { | |
| 320 if (callArgument->hasObjectId()) { | |
| 321 std::unique_ptr<RemoteObjectId> remoteObjectId = | |
| 322 RemoteObjectId::parse(errorString, callArgument->getObjectId("")); | |
| 323 if (!remoteObjectId) return v8::MaybeLocal<v8::Value>(); | |
| 324 if (remoteObjectId->contextId() != m_context->contextId()) { | |
| 325 *errorString = | |
| 326 "Argument should belong to the same JavaScript world as target " | |
| 327 "object"; | |
| 328 return v8::MaybeLocal<v8::Value>(); | |
| 329 } | |
| 330 v8::Local<v8::Value> object; | |
| 331 if (!findObject(errorString, *remoteObjectId, &object)) | |
| 332 return v8::MaybeLocal<v8::Value>(); | |
| 333 return object; | |
| 334 } | |
| 335 if (callArgument->hasValue() || callArgument->hasUnserializableValue()) { | |
| 336 String16 value = | |
| 337 callArgument->hasValue() | |
| 338 ? callArgument->getValue(nullptr)->toJSONString() | |
| 339 : "Number(\"" + callArgument->getUnserializableValue("") + "\")"; | |
| 340 v8::Local<v8::Value> object; | |
| 341 if (!m_context->inspector() | |
| 342 ->compileAndRunInternalScript( | |
| 343 m_context->context(), toV8String(m_context->isolate(), value)) | |
| 344 .ToLocal(&object)) { | |
| 345 *errorString = "Couldn't parse value object in call argument"; | |
| 346 return v8::MaybeLocal<v8::Value>(); | |
| 347 } | |
| 348 return object; | |
| 349 } | |
| 350 return v8::Undefined(m_context->isolate()); | |
| 351 } | |
| 352 | |
| 353 std::unique_ptr<protocol::Runtime::ExceptionDetails> | |
| 354 InjectedScript::createExceptionDetails(ErrorString* errorString, | |
| 355 const v8::TryCatch& tryCatch, | |
| 356 const String16& objectGroup, | |
| 357 bool generatePreview) { | |
| 358 if (!tryCatch.HasCaught()) return nullptr; | |
| 359 v8::Local<v8::Message> message = tryCatch.Message(); | |
| 360 v8::Local<v8::Value> exception = tryCatch.Exception(); | |
| 361 String16 messageText = | |
| 362 message.IsEmpty() ? String16() : toProtocolString(message->Get()); | |
| 363 std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails = | |
| 364 protocol::Runtime::ExceptionDetails::create() | |
| 365 .setExceptionId(m_context->inspector()->nextExceptionId()) | |
| 366 .setText(exception.IsEmpty() ? messageText : String16("Uncaught")) | |
| 367 .setLineNumber( | |
| 368 message.IsEmpty() | |
| 369 ? 0 | |
| 370 : message->GetLineNumber(m_context->context()).FromMaybe(1) - | |
| 371 1) | |
| 372 .setColumnNumber( | |
| 373 message.IsEmpty() | |
| 374 ? 0 | |
| 375 : message->GetStartColumn(m_context->context()).FromMaybe(0)) | |
| 376 .build(); | |
| 377 if (!message.IsEmpty()) { | |
| 378 exceptionDetails->setScriptId( | |
| 379 String16::fromInteger(message->GetScriptOrigin().ScriptID()->Value())); | |
| 380 v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace(); | |
| 381 if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) | |
| 382 exceptionDetails->setStackTrace(m_context->inspector() | |
| 383 ->debugger() | |
| 384 ->createStackTrace(stackTrace) | |
| 385 ->buildInspectorObjectImpl()); | |
| 386 } | |
| 387 if (!exception.IsEmpty()) { | |
| 388 std::unique_ptr<protocol::Runtime::RemoteObject> wrapped = wrapObject( | |
| 389 errorString, exception, objectGroup, false /* forceValueType */, | |
| 390 generatePreview && !exception->IsNativeError()); | |
| 391 if (!wrapped) return nullptr; | |
| 392 exceptionDetails->setException(std::move(wrapped)); | |
| 393 } | |
| 394 return exceptionDetails; | |
| 395 } | |
| 396 | |
| 397 void InjectedScript::wrapEvaluateResult( | |
| 398 ErrorString* errorString, v8::MaybeLocal<v8::Value> maybeResultValue, | |
| 399 const v8::TryCatch& tryCatch, const String16& objectGroup, | |
| 400 bool returnByValue, bool generatePreview, | |
| 401 std::unique_ptr<protocol::Runtime::RemoteObject>* result, | |
| 402 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { | |
| 403 v8::Local<v8::Value> resultValue; | |
| 404 if (!tryCatch.HasCaught()) { | |
| 405 if (hasInternalError(errorString, !maybeResultValue.ToLocal(&resultValue))) | |
| 406 return; | |
| 407 std::unique_ptr<RemoteObject> remoteObject = wrapObject( | |
| 408 errorString, resultValue, objectGroup, returnByValue, generatePreview); | |
| 409 if (!remoteObject) return; | |
| 410 if (objectGroup == "console") | |
| 411 m_lastEvaluationResult.Reset(m_context->isolate(), resultValue); | |
| 412 *result = std::move(remoteObject); | |
| 413 } else { | |
| 414 v8::Local<v8::Value> exception = tryCatch.Exception(); | |
| 415 std::unique_ptr<RemoteObject> remoteObject = | |
| 416 wrapObject(errorString, exception, objectGroup, false, | |
| 417 generatePreview && !exception->IsNativeError()); | |
| 418 if (!remoteObject) return; | |
| 419 // We send exception in result for compatibility reasons, even though it's | |
| 420 // accessible through exceptionDetails.exception. | |
| 421 *result = std::move(remoteObject); | |
| 422 *exceptionDetails = createExceptionDetails(errorString, tryCatch, | |
| 423 objectGroup, generatePreview); | |
| 424 } | |
| 425 } | |
| 426 | |
| 427 v8::Local<v8::Object> InjectedScript::commandLineAPI() { | |
| 428 if (m_commandLineAPI.IsEmpty()) | |
| 429 m_commandLineAPI.Reset(m_context->isolate(), | |
| 430 V8Console::createCommandLineAPI(m_context)); | |
| 431 return m_commandLineAPI.Get(m_context->isolate()); | |
| 432 } | |
| 433 | |
| 434 InjectedScript::Scope::Scope(ErrorString* errorString, | |
| 435 V8InspectorImpl* inspector, int contextGroupId) | |
| 436 : m_errorString(errorString), | |
| 437 m_inspector(inspector), | |
| 438 m_contextGroupId(contextGroupId), | |
| 439 m_injectedScript(nullptr), | |
| 440 m_handleScope(inspector->isolate()), | |
| 441 m_tryCatch(inspector->isolate()), | |
| 442 m_ignoreExceptionsAndMuteConsole(false), | |
| 443 m_previousPauseOnExceptionsState(V8Debugger::DontPauseOnExceptions), | |
| 444 m_userGesture(false) {} | |
| 445 | |
| 446 bool InjectedScript::Scope::initialize() { | |
| 447 cleanup(); | |
| 448 // TODO(dgozman): what if we reattach to the same context group during | |
| 449 // evaluate? Introduce a session id? | |
| 450 V8InspectorSessionImpl* session = | |
| 451 m_inspector->sessionForContextGroup(m_contextGroupId); | |
| 452 if (!session) { | |
| 453 *m_errorString = "Internal error"; | |
| 454 return false; | |
| 455 } | |
| 456 findInjectedScript(session); | |
| 457 if (!m_injectedScript) return false; | |
| 458 m_context = m_injectedScript->context()->context(); | |
| 459 m_context->Enter(); | |
| 460 return true; | |
| 461 } | |
| 462 | |
| 463 bool InjectedScript::Scope::installCommandLineAPI() { | |
| 464 DCHECK(m_injectedScript && !m_context.IsEmpty() && | |
| 465 !m_commandLineAPIScope.get()); | |
| 466 m_commandLineAPIScope.reset(new V8Console::CommandLineAPIScope( | |
| 467 m_context, m_injectedScript->commandLineAPI(), m_context->Global())); | |
| 468 return true; | |
| 469 } | |
| 470 | |
| 471 void InjectedScript::Scope::ignoreExceptionsAndMuteConsole() { | |
| 472 DCHECK(!m_ignoreExceptionsAndMuteConsole); | |
| 473 m_ignoreExceptionsAndMuteConsole = true; | |
| 474 m_inspector->client()->muteMetrics(m_contextGroupId); | |
| 475 m_inspector->muteExceptions(m_contextGroupId); | |
| 476 m_previousPauseOnExceptionsState = | |
| 477 setPauseOnExceptionsState(V8Debugger::DontPauseOnExceptions); | |
| 478 } | |
| 479 | |
| 480 V8Debugger::PauseOnExceptionsState | |
| 481 InjectedScript::Scope::setPauseOnExceptionsState( | |
| 482 V8Debugger::PauseOnExceptionsState newState) { | |
| 483 if (!m_inspector->debugger()->enabled()) return newState; | |
| 484 V8Debugger::PauseOnExceptionsState presentState = | |
| 485 m_inspector->debugger()->getPauseOnExceptionsState(); | |
| 486 if (presentState != newState) | |
| 487 m_inspector->debugger()->setPauseOnExceptionsState(newState); | |
| 488 return presentState; | |
| 489 } | |
| 490 | |
| 491 void InjectedScript::Scope::pretendUserGesture() { | |
| 492 DCHECK(!m_userGesture); | |
| 493 m_userGesture = true; | |
| 494 m_inspector->client()->beginUserGesture(); | |
| 495 } | |
| 496 | |
| 497 void InjectedScript::Scope::cleanup() { | |
| 498 m_commandLineAPIScope.reset(); | |
| 499 if (!m_context.IsEmpty()) { | |
| 500 m_context->Exit(); | |
| 501 m_context.Clear(); | |
| 502 } | |
| 503 } | |
| 504 | |
| 505 InjectedScript::Scope::~Scope() { | |
| 506 if (m_ignoreExceptionsAndMuteConsole) { | |
| 507 setPauseOnExceptionsState(m_previousPauseOnExceptionsState); | |
| 508 m_inspector->client()->unmuteMetrics(m_contextGroupId); | |
| 509 m_inspector->unmuteExceptions(m_contextGroupId); | |
| 510 } | |
| 511 if (m_userGesture) m_inspector->client()->endUserGesture(); | |
| 512 cleanup(); | |
| 513 } | |
| 514 | |
| 515 InjectedScript::ContextScope::ContextScope(ErrorString* errorString, | |
| 516 V8InspectorImpl* inspector, | |
| 517 int contextGroupId, | |
| 518 int executionContextId) | |
| 519 : InjectedScript::Scope(errorString, inspector, contextGroupId), | |
| 520 m_executionContextId(executionContextId) {} | |
| 521 | |
| 522 InjectedScript::ContextScope::~ContextScope() {} | |
| 523 | |
| 524 void InjectedScript::ContextScope::findInjectedScript( | |
| 525 V8InspectorSessionImpl* session) { | |
| 526 m_injectedScript = | |
| 527 session->findInjectedScript(m_errorString, m_executionContextId); | |
| 528 } | |
| 529 | |
| 530 InjectedScript::ObjectScope::ObjectScope(ErrorString* errorString, | |
| 531 V8InspectorImpl* inspector, | |
| 532 int contextGroupId, | |
| 533 const String16& remoteObjectId) | |
| 534 : InjectedScript::Scope(errorString, inspector, contextGroupId), | |
| 535 m_remoteObjectId(remoteObjectId) {} | |
| 536 | |
| 537 InjectedScript::ObjectScope::~ObjectScope() {} | |
| 538 | |
| 539 void InjectedScript::ObjectScope::findInjectedScript( | |
| 540 V8InspectorSessionImpl* session) { | |
| 541 std::unique_ptr<RemoteObjectId> remoteId = | |
| 542 RemoteObjectId::parse(m_errorString, m_remoteObjectId); | |
| 543 if (!remoteId) return; | |
| 544 InjectedScript* injectedScript = | |
| 545 session->findInjectedScript(m_errorString, remoteId.get()); | |
| 546 if (!injectedScript) return; | |
| 547 m_objectGroupName = injectedScript->objectGroupName(*remoteId); | |
| 548 if (!injectedScript->findObject(m_errorString, *remoteId, &m_object)) return; | |
| 549 m_injectedScript = injectedScript; | |
| 550 } | |
| 551 | |
| 552 InjectedScript::CallFrameScope::CallFrameScope(ErrorString* errorString, | |
| 553 V8InspectorImpl* inspector, | |
| 554 int contextGroupId, | |
| 555 const String16& remoteObjectId) | |
| 556 : InjectedScript::Scope(errorString, inspector, contextGroupId), | |
| 557 m_remoteCallFrameId(remoteObjectId) {} | |
| 558 | |
| 559 InjectedScript::CallFrameScope::~CallFrameScope() {} | |
| 560 | |
| 561 void InjectedScript::CallFrameScope::findInjectedScript( | |
| 562 V8InspectorSessionImpl* session) { | |
| 563 std::unique_ptr<RemoteCallFrameId> remoteId = | |
| 564 RemoteCallFrameId::parse(m_errorString, m_remoteCallFrameId); | |
| 565 if (!remoteId) return; | |
| 566 m_frameOrdinal = static_cast<size_t>(remoteId->frameOrdinal()); | |
| 567 m_injectedScript = session->findInjectedScript(m_errorString, remoteId.get()); | |
| 568 } | |
| 569 | |
| 570 } // namespace v8_inspector | |
| OLD | NEW |