OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 16 matching lines...) Expand all Loading... |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | 30 |
31 #include "config.h" | 31 #include "config.h" |
32 | 32 |
33 | 33 |
34 #include "core/inspector/InjectedScript.h" | 34 #include "core/inspector/InjectedScript.h" |
35 | 35 |
36 #include "bindings/core/v8/ScriptFunctionCall.h" | 36 #include "bindings/core/v8/ScriptFunctionCall.h" |
| 37 #include "bindings/core/v8/V8Binding.h" |
37 #include "core/inspector/InjectedScriptHost.h" | 38 #include "core/inspector/InjectedScriptHost.h" |
| 39 #include "core/inspector/InspectorInstrumentation.h" |
| 40 #include "core/inspector/InspectorTraceEvents.h" |
38 #include "core/inspector/JSONParser.h" | 41 #include "core/inspector/JSONParser.h" |
39 #include "platform/JSONValues.h" | 42 #include "platform/JSONValues.h" |
40 #include "wtf/text/WTFString.h" | 43 #include "wtf/text/WTFString.h" |
41 | 44 |
42 using blink::TypeBuilder::Array; | 45 using blink::TypeBuilder::Array; |
43 using blink::TypeBuilder::Debugger::CallFrame; | 46 using blink::TypeBuilder::Debugger::CallFrame; |
44 using blink::TypeBuilder::Debugger::CollectionEntry; | 47 using blink::TypeBuilder::Debugger::CollectionEntry; |
45 using blink::TypeBuilder::Debugger::FunctionDetails; | 48 using blink::TypeBuilder::Debugger::FunctionDetails; |
46 using blink::TypeBuilder::Debugger::GeneratorObjectDetails; | 49 using blink::TypeBuilder::Debugger::GeneratorObjectDetails; |
47 using blink::TypeBuilder::Runtime::PropertyDescriptor; | 50 using blink::TypeBuilder::Runtime::PropertyDescriptor; |
48 using blink::TypeBuilder::Runtime::InternalPropertyDescriptor; | 51 using blink::TypeBuilder::Runtime::InternalPropertyDescriptor; |
49 using blink::TypeBuilder::Runtime::RemoteObject; | 52 using blink::TypeBuilder::Runtime::RemoteObject; |
50 | 53 |
51 namespace blink { | 54 namespace blink { |
52 | 55 |
| 56 PassRefPtr<JSONValue> toJSONValue(const ScriptValue& value) |
| 57 { |
| 58 ScriptState* scriptState = value.scriptState(); |
| 59 ASSERT(scriptState->contextIsValid()); |
| 60 ScriptState::Scope scope(scriptState); |
| 61 NonThrowableExceptionState exceptionState; |
| 62 return ScriptValue::to<JSONValuePtr>(scriptState->isolate(), value, exceptio
nState); |
| 63 } |
| 64 |
| 65 static PassRefPtr<TypeBuilder::Debugger::ExceptionDetails> toExceptionDetails(Pa
ssRefPtr<JSONObject> object) |
| 66 { |
| 67 String text; |
| 68 if (!object->getString("text", &text)) |
| 69 return nullptr; |
| 70 |
| 71 RefPtr<TypeBuilder::Debugger::ExceptionDetails> exceptionDetails = TypeBuild
er::Debugger::ExceptionDetails::create().setText(text); |
| 72 String url; |
| 73 if (object->getString("url", &url)) |
| 74 exceptionDetails->setUrl(url); |
| 75 int line = 0; |
| 76 if (object->getNumber("line", &line)) |
| 77 exceptionDetails->setLine(line); |
| 78 int column = 0; |
| 79 if (object->getNumber("column", &column)) |
| 80 exceptionDetails->setColumn(column); |
| 81 int originScriptId = 0; |
| 82 object->getNumber("scriptId", &originScriptId); |
| 83 |
| 84 RefPtr<JSONArray> stackTrace = object->getArray("stackTrace"); |
| 85 if (stackTrace && stackTrace->length() > 0) { |
| 86 RefPtr<TypeBuilder::Array<TypeBuilder::Console::CallFrame>> frames = Typ
eBuilder::Array<TypeBuilder::Console::CallFrame>::create(); |
| 87 for (unsigned i = 0; i < stackTrace->length(); ++i) { |
| 88 RefPtr<JSONObject> stackFrame = stackTrace->get(i)->asObject(); |
| 89 int lineNumber = 0; |
| 90 stackFrame->getNumber("lineNumber", &lineNumber); |
| 91 int column = 0; |
| 92 stackFrame->getNumber("column", &column); |
| 93 int scriptId = 0; |
| 94 stackFrame->getNumber("scriptId", &scriptId); |
| 95 if (i == 0 && scriptId == originScriptId) |
| 96 originScriptId = 0; |
| 97 |
| 98 String sourceURL; |
| 99 stackFrame->getString("scriptNameOrSourceURL", &sourceURL); |
| 100 String functionName; |
| 101 stackFrame->getString("functionName", &functionName); |
| 102 |
| 103 RefPtr<TypeBuilder::Console::CallFrame> callFrame = TypeBuilder::Con
sole::CallFrame::create() |
| 104 .setFunctionName(functionName) |
| 105 .setScriptId(String::number(scriptId)) |
| 106 .setUrl(sourceURL) |
| 107 .setLineNumber(lineNumber) |
| 108 .setColumnNumber(column); |
| 109 |
| 110 frames->addItem(callFrame.release()); |
| 111 } |
| 112 exceptionDetails->setStackTrace(frames.release()); |
| 113 } |
| 114 if (originScriptId) |
| 115 exceptionDetails->setScriptId(String::number(originScriptId)); |
| 116 return exceptionDetails.release(); |
| 117 } |
| 118 |
53 InjectedScript::InjectedScript() | 119 InjectedScript::InjectedScript() |
54 : InjectedScriptBase("InjectedScript") | 120 : m_inspectedStateAccessCheck(nullptr) |
55 { | 121 { |
56 } | 122 } |
57 | 123 |
58 InjectedScript::InjectedScript(ScriptValue injectedScriptObject, InspectedStateA
ccessCheck accessCheck, PassRefPtr<InjectedScriptNative> injectedScriptNative) | 124 InjectedScript::InjectedScript(ScriptValue injectedScriptObject, InspectedStateA
ccessCheck accessCheck, PassRefPtr<InjectedScriptNative> injectedScriptNative) |
59 : InjectedScriptBase("InjectedScript", injectedScriptObject, accessCheck) | 125 : m_injectedScriptObject(injectedScriptObject) |
| 126 , m_inspectedStateAccessCheck(accessCheck) |
60 , m_native(injectedScriptNative) | 127 , m_native(injectedScriptNative) |
61 { | 128 { |
62 } | 129 } |
63 | 130 |
| 131 InjectedScript::~InjectedScript() |
| 132 { |
| 133 } |
| 134 |
64 void InjectedScript::evaluate(ErrorString* errorString, const String& expression
, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, boo
l generatePreview, RefPtr<TypeBuilder::Runtime::RemoteObject>* result, TypeBuild
er::OptOutput<bool>* wasThrown, RefPtr<TypeBuilder::Debugger::ExceptionDetails>*
exceptionDetails) | 135 void InjectedScript::evaluate(ErrorString* errorString, const String& expression
, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, boo
l generatePreview, RefPtr<TypeBuilder::Runtime::RemoteObject>* result, TypeBuild
er::OptOutput<bool>* wasThrown, RefPtr<TypeBuilder::Debugger::ExceptionDetails>*
exceptionDetails) |
65 { | 136 { |
66 ScriptFunctionCall function(injectedScriptObject(), "evaluate"); | 137 ScriptFunctionCall function(injectedScriptObject(), "evaluate"); |
67 function.appendArgument(expression); | 138 function.appendArgument(expression); |
68 function.appendArgument(objectGroup); | 139 function.appendArgument(objectGroup); |
69 function.appendArgument(includeCommandLineAPI); | 140 function.appendArgument(includeCommandLineAPI); |
70 function.appendArgument(returnByValue); | 141 function.appendArgument(returnByValue); |
71 function.appendArgument(generatePreview); | 142 function.appendArgument(generatePreview); |
72 makeEvalCall(errorString, function, result, wasThrown, exceptionDetails); | 143 makeEvalCall(errorString, function, result, wasThrown, exceptionDetails); |
73 } | 144 } |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 | 456 |
386 void InjectedScript::setCustomObjectFormatterEnabled(bool enabled) | 457 void InjectedScript::setCustomObjectFormatterEnabled(bool enabled) |
387 { | 458 { |
388 ASSERT(!isEmpty()); | 459 ASSERT(!isEmpty()); |
389 ScriptFunctionCall function(injectedScriptObject(), "setCustomObjectFormatte
rEnabled"); | 460 ScriptFunctionCall function(injectedScriptObject(), "setCustomObjectFormatte
rEnabled"); |
390 function.appendArgument(enabled); | 461 function.appendArgument(enabled); |
391 RefPtr<JSONValue> result; | 462 RefPtr<JSONValue> result; |
392 makeCall(function, &result); | 463 makeCall(function, &result); |
393 } | 464 } |
394 | 465 |
| 466 void InjectedScript::initialize(ScriptValue injectedScriptObject, InspectedState
AccessCheck accessCheck) |
| 467 { |
| 468 m_injectedScriptObject = injectedScriptObject; |
| 469 m_inspectedStateAccessCheck = accessCheck; |
| 470 } |
| 471 |
| 472 bool InjectedScript::canAccessInspectedWindow() const |
| 473 { |
| 474 ASSERT(!isEmpty()); |
| 475 return m_inspectedStateAccessCheck(m_injectedScriptObject.scriptState()); |
| 476 } |
| 477 |
| 478 const ScriptValue& InjectedScript::injectedScriptObject() const |
| 479 { |
| 480 return m_injectedScriptObject; |
| 481 } |
| 482 |
| 483 ScriptValue InjectedScript::callFunctionWithEvalEnabled(ScriptFunctionCall& func
tion, bool& hadException) const |
| 484 { |
| 485 ASSERT(!isEmpty()); |
| 486 ExecutionContext* executionContext = m_injectedScriptObject.scriptState()->e
xecutionContext(); |
| 487 ScriptState::Scope scope(m_injectedScriptObject.scriptState()); |
| 488 v8::Local<v8::Function> functionObj = function.function(); |
| 489 DevToolsFunctionInfo info(functionObj); |
| 490 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willCallFu
nction(executionContext, info); |
| 491 |
| 492 ScriptState* scriptState = m_injectedScriptObject.scriptState(); |
| 493 bool evalIsDisabled = false; |
| 494 if (scriptState) { |
| 495 evalIsDisabled = !scriptState->evalEnabled(); |
| 496 // Temporarily enable allow evals for inspector. |
| 497 if (evalIsDisabled) |
| 498 scriptState->setEvalEnabled(true); |
| 499 } |
| 500 |
| 501 ScriptValue resultValue = function.call(hadException); |
| 502 |
| 503 if (evalIsDisabled) |
| 504 scriptState->setEvalEnabled(false); |
| 505 |
| 506 InspectorInstrumentation::didCallFunction(cookie); |
| 507 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Update
Counters", TRACE_EVENT_SCOPE_THREAD, "data", InspectorUpdateCountersEvent::data(
)); |
| 508 return resultValue; |
| 509 } |
| 510 |
| 511 void InjectedScript::makeCall(ScriptFunctionCall& function, RefPtr<JSONValue>* r
esult) |
| 512 { |
| 513 if (isEmpty() || !canAccessInspectedWindow()) { |
| 514 *result = JSONValue::null(); |
| 515 return; |
| 516 } |
| 517 |
| 518 bool hadException = false; |
| 519 ScriptValue resultValue = callFunctionWithEvalEnabled(function, hadException
); |
| 520 |
| 521 ASSERT(!hadException); |
| 522 if (!hadException) { |
| 523 *result = toJSONValue(resultValue); |
| 524 if (!*result) |
| 525 *result = JSONString::create(String::format("Object has too long ref
erence chain(must not be longer than %d)", JSONValue::maxDepth)); |
| 526 } else { |
| 527 *result = JSONString::create("Exception while making a call."); |
| 528 } |
| 529 } |
| 530 |
| 531 void InjectedScript::makeEvalCall(ErrorString* errorString, ScriptFunctionCall&
function, RefPtr<TypeBuilder::Runtime::RemoteObject>* objectResult, TypeBuilder:
:OptOutput<bool>* wasThrown, RefPtr<TypeBuilder::Debugger::ExceptionDetails>* ex
ceptionDetails) |
| 532 { |
| 533 RefPtr<JSONValue> result; |
| 534 makeCall(function, &result); |
| 535 if (!result) { |
| 536 *errorString = "Internal error: result value is empty"; |
| 537 return; |
| 538 } |
| 539 if (result->type() == JSONValue::TypeString) { |
| 540 result->asString(errorString); |
| 541 ASSERT(errorString->length()); |
| 542 return; |
| 543 } |
| 544 RefPtr<JSONObject> resultPair = result->asObject(); |
| 545 if (!resultPair) { |
| 546 *errorString = "Internal error: result is not an Object"; |
| 547 return; |
| 548 } |
| 549 RefPtr<JSONObject> resultObj = resultPair->getObject("result"); |
| 550 bool wasThrownVal = false; |
| 551 if (!resultObj || !resultPair->getBoolean("wasThrown", &wasThrownVal)) { |
| 552 *errorString = "Internal error: result is not a pair of value and wasThr
own flag"; |
| 553 return; |
| 554 } |
| 555 if (wasThrownVal) { |
| 556 RefPtr<JSONObject> objectExceptionDetails = resultPair->getObject("excep
tionDetails"); |
| 557 if (objectExceptionDetails) |
| 558 *exceptionDetails = toExceptionDetails(objectExceptionDetails.releas
e()); |
| 559 } |
| 560 *objectResult = TypeBuilder::Runtime::RemoteObject::runtimeCast(resultObj); |
| 561 *wasThrown = wasThrownVal; |
| 562 } |
| 563 |
| 564 void InjectedScript::makeCallWithExceptionDetails(ScriptFunctionCall& function,
RefPtr<JSONValue>* result, RefPtr<TypeBuilder::Debugger::ExceptionDetails>* exce
ptionDetails) |
| 565 { |
| 566 ScriptState::Scope scope(injectedScriptObject().scriptState()); |
| 567 v8::TryCatch tryCatch; |
| 568 ScriptValue resultValue = function.callWithoutExceptionHandling(); |
| 569 if (tryCatch.HasCaught()) { |
| 570 v8::Local<v8::Message> message = tryCatch.Message(); |
| 571 String text = !message.IsEmpty() ? toCoreStringWithUndefinedOrNullCheck(
message->Get()) : "Internal error"; |
| 572 *exceptionDetails = TypeBuilder::Debugger::ExceptionDetails::create().se
tText(text); |
| 573 } else { |
| 574 *result = toJSONValue(resultValue); |
| 575 if (!*result) |
| 576 *result = JSONString::create(String::format("Object has too long ref
erence chain(must not be longer than %d)", JSONValue::maxDepth)); |
| 577 } |
| 578 } |
| 579 |
395 } // namespace blink | 580 } // namespace blink |
396 | 581 |
OLD | NEW |