Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1470)

Unified Diff: third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp

Issue 2035653006: [DevTools] Move Console to v8 inspector. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: all tests pass Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..63d899ed8df0e69f07c45f707a6987c9efc176eb
--- /dev/null
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp
@@ -0,0 +1,428 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/v8_inspector/V8ConsoleMessage.h"
+
+#include "platform/v8_inspector/InspectedContext.h"
+#include "platform/v8_inspector/V8ConsoleAgentImpl.h"
+#include "platform/v8_inspector/V8DebuggerImpl.h"
+#include "platform/v8_inspector/V8InspectorSessionImpl.h"
+#include "platform/v8_inspector/V8StackTraceImpl.h"
+#include "platform/v8_inspector/V8StringUtil.h"
+#include "platform/v8_inspector/public/V8DebuggerClient.h"
+
+namespace blink {
+
+namespace {
+
+String messageSourceValue(MessageSource source)
+{
+ switch (source) {
+ case XMLMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Xml;
+ case JSMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Javascript;
+ case NetworkMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Network;
+ case ConsoleAPIMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::ConsoleApi;
+ case StorageMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Storage;
+ case AppCacheMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Appcache;
+ case RenderingMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Rendering;
+ case SecurityMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Security;
+ case OtherMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Other;
+ case DeprecationMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Deprecation;
+ }
+ return protocol::Console::ConsoleMessage::SourceEnum::Other;
+}
+
+
+String messageTypeValue(MessageType type)
+{
+ switch (type) {
+ case LogMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Log;
+ case ClearMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Clear;
+ case DirMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Dir;
+ case DirXMLMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Dirxml;
+ case TableMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Table;
+ case TraceMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Trace;
+ case StartGroupMessageType: return protocol::Console::ConsoleMessage::TypeEnum::StartGroup;
+ case StartGroupCollapsedMessageType: return protocol::Console::ConsoleMessage::TypeEnum::StartGroupCollapsed;
+ case EndGroupMessageType: return protocol::Console::ConsoleMessage::TypeEnum::EndGroup;
+ case AssertMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Assert;
+ case TimeEndMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Log;
+ case CountMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Log;
+ }
+ return protocol::Console::ConsoleMessage::TypeEnum::Log;
+}
+
+String messageLevelValue(MessageLevel level)
+{
+ switch (level) {
+ case DebugMessageLevel: return protocol::Console::ConsoleMessage::LevelEnum::Debug;
+ case LogMessageLevel: return protocol::Console::ConsoleMessage::LevelEnum::Log;
+ case WarningMessageLevel: return protocol::Console::ConsoleMessage::LevelEnum::Warning;
+ case ErrorMessageLevel: return protocol::Console::ConsoleMessage::LevelEnum::Error;
+ case InfoMessageLevel: return protocol::Console::ConsoleMessage::LevelEnum::Info;
+ case RevokedErrorMessageLevel: return protocol::Console::ConsoleMessage::LevelEnum::RevokedError;
+ }
+ return protocol::Console::ConsoleMessage::LevelEnum::Log;
+}
+
+const unsigned maxConsoleMessageCount = 1000;
+const unsigned maxArrayItemsLimit = 10000;
+const unsigned maxStackDepthLimit = 32;
+
+class V8ValueStringBuilder {
+public:
+ static String16 toString(v8::Local<v8::Value> value, v8::Isolate* isolate)
+ {
+ V8ValueStringBuilder builder(isolate);
+ if (!builder.append(value))
+ return String16();
+ return builder.toString();
+ }
+
+private:
+ enum {
+ IgnoreNull = 1 << 0,
+ IgnoreUndefined = 1 << 1,
+ };
+
+ V8ValueStringBuilder(v8::Isolate* isolate)
+ : m_arrayLimit(maxArrayItemsLimit)
+ , m_isolate(isolate)
+ , m_tryCatch(isolate)
+ {
+ }
+
+ bool append(v8::Local<v8::Value> value, unsigned ignoreOptions = 0)
+ {
+ if (value.IsEmpty())
+ return true;
+ if ((ignoreOptions & IgnoreNull) && value->IsNull())
+ return true;
+ if ((ignoreOptions & IgnoreUndefined) && value->IsUndefined())
+ return true;
+ if (value->IsString())
+ return append(v8::Local<v8::String>::Cast(value));
+ if (value->IsStringObject())
+ return append(v8::Local<v8::StringObject>::Cast(value)->ValueOf());
+ if (value->IsSymbol())
+ return append(v8::Local<v8::Symbol>::Cast(value));
+ if (value->IsSymbolObject())
+ return append(v8::Local<v8::SymbolObject>::Cast(value)->ValueOf());
+ if (value->IsNumberObject()) {
+ m_builder.appendNumber(v8::Local<v8::NumberObject>::Cast(value)->ValueOf());
+ return true;
+ }
+ if (value->IsBooleanObject()) {
+ m_builder.append(v8::Local<v8::BooleanObject>::Cast(value)->ValueOf() ? "true" : "false");
+ return true;
+ }
+ if (value->IsArray())
+ return append(v8::Local<v8::Array>::Cast(value));
+ if (value->IsProxy()) {
+ m_builder.append("[object Proxy]");
+ return true;
+ }
+ if (value->IsObject()
+ && !value->IsDate()
+ && !value->IsFunction()
+ && !value->IsNativeError()
+ && !value->IsRegExp()) {
+ v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
+ v8::Local<v8::String> stringValue;
+ if (object->ObjectProtoToString(m_isolate->GetCurrentContext()).ToLocal(&stringValue))
+ return append(stringValue);
+ }
+ v8::Local<v8::String> stringValue;
+ if (!value->ToString(m_isolate->GetCurrentContext()).ToLocal(&stringValue))
+ return false;
+ return append(stringValue);
+ }
+
+ bool append(v8::Local<v8::Array> array)
+ {
+ if (m_visitedArrays.contains(array))
+ return true;
+ uint32_t length = array->Length();
+ if (length > m_arrayLimit)
+ return false;
+ if (m_visitedArrays.size() > maxStackDepthLimit)
+ return false;
+
+ bool result = true;
+ m_arrayLimit -= length;
+ m_visitedArrays.append(array);
+ for (uint32_t i = 0; i < length; ++i) {
+ if (i)
+ m_builder.append(',');
+ if (!append(array->Get(i), IgnoreNull | IgnoreUndefined)) {
+ result = false;
+ break;
+ }
+ }
+ m_visitedArrays.removeLast();
+ return result;
+ }
+
+ bool append(v8::Local<v8::Symbol> symbol)
+ {
+ m_builder.append("Symbol(");
+ bool result = append(symbol->Name(), IgnoreUndefined);
+ m_builder.append(')');
+ return result;
+ }
+
+ bool append(v8::Local<v8::String> string)
+ {
+ if (m_tryCatch.HasCaught())
+ return false;
+ if (!string.IsEmpty())
+ m_builder.append(toProtocolString(string));
+ return true;
+ }
+
+ String16 toString()
+ {
+ if (m_tryCatch.HasCaught())
+ return String16();
+ return m_builder.toString();
+ }
+
+ uint32_t m_arrayLimit;
+ v8::Isolate* m_isolate;
+ String16Builder m_builder;
+ Vector<v8::Local<v8::Array>> m_visitedArrays;
+ v8::TryCatch m_tryCatch;
+};
+
+} // namespace
+
+V8ConsoleMessage::V8ConsoleMessage(
+ double timestampMS,
+ MessageSource source,
+ MessageLevel level,
+ const String16& message,
+ const String16& url,
+ unsigned lineNumber,
+ unsigned columnNumber,
+ std::unique_ptr<V8StackTrace> stackTrace,
+ int scriptId,
+ const String16& requestIdentifier)
+ : m_timestamp(timestampMS / 1000.0)
+ , m_source(source)
+ , m_level(level)
+ , m_message(message)
+ , m_url(url)
+ , m_lineNumber(lineNumber)
+ , m_columnNumber(columnNumber)
+ , m_stackTrace(std::move(stackTrace))
+ , m_scriptId(scriptId)
+ , m_requestIdentifier(requestIdentifier)
+ , m_contextId(0)
+ , m_type(LogMessageType)
+ , m_messageId(0)
+ , m_relatedMessageId(0)
+{
+}
+
+V8ConsoleMessage::~V8ConsoleMessage()
+{
+}
+
+std::unique_ptr<protocol::Console::ConsoleMessage> V8ConsoleMessage::buildInspectorObject(V8InspectorSessionImpl* session, bool generatePreview) const
+{
+ std::unique_ptr<protocol::Console::ConsoleMessage> result =
+ protocol::Console::ConsoleMessage::create()
+ .setSource(messageSourceValue(m_source))
+ .setLevel(messageLevelValue(m_level))
+ .setText(m_message)
+ .setTimestamp(m_timestamp)
+ .build();
+ result->setType(messageTypeValue(m_type));
+ result->setLine(static_cast<int>(m_lineNumber));
+ result->setColumn(static_cast<int>(m_columnNumber));
+ if (m_scriptId)
+ result->setScriptId(String::number(m_scriptId));
+ result->setUrl(m_url);
+ if (m_source == NetworkMessageSource && !m_requestIdentifier.isEmpty())
+ result->setNetworkRequestId(m_requestIdentifier);
+ if (m_contextId)
+ result->setExecutionContextId(m_contextId);
+ appendArguments(result.get(), session, generatePreview);
+ if (m_stackTrace)
+ result->setStack(m_stackTrace->buildInspectorObject());
+ if (m_messageId)
+ result->setMessageId(m_messageId);
+ if (m_relatedMessageId)
+ result->setRelatedMessageId(m_relatedMessageId);
+ return result;
+}
+
+void V8ConsoleMessage::appendArguments(protocol::Console::ConsoleMessage* result, V8InspectorSessionImpl* session, bool generatePreview) const
+{
+ if (!m_arguments.size() || !m_contextId)
+ return;
+ const V8DebuggerImpl::ContextByIdMap* contexts = session->debugger()->contextGroup(session->contextGroupId());
+ if (!contexts || !contexts->contains(m_contextId))
+ return;
+
+ InspectedContext* inspectedContext = contexts->get(m_contextId);
+ v8::Isolate* isolate = inspectedContext->isolate();
+ v8::HandleScope handles(isolate);
+ v8::Local<v8::Context> context = inspectedContext->context();
+
+ std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>> args = protocol::Array<protocol::Runtime::RemoteObject>::create();
+ if (m_type == TableMessageType && generatePreview) {
+ v8::Local<v8::Value> table = m_arguments[0]->Get(isolate);
+ v8::Local<v8::Value> columns = m_arguments.size() > 1 ? m_arguments[1]->Get(isolate) : v8::Local<v8::Value>();
+ std::unique_ptr<protocol::Runtime::RemoteObject> wrapped = session->wrapTable(context, table, columns);
+ if (wrapped)
+ args->addItem(std::move(wrapped));
+ else
+ args = nullptr;
+ } else {
+ for (size_t i = 0; i < m_arguments.size(); ++i) {
+ std::unique_ptr<protocol::Runtime::RemoteObject> wrapped = session->wrapObject(context, m_arguments[i]->Get(isolate), "console", generatePreview);
+ if (!wrapped) {
+ args = nullptr;
+ break;
+ }
+ args->addItem(std::move(wrapped));
+ }
+ }
+ if (args)
+ result->setParameters(std::move(args));
+}
+
+unsigned V8ConsoleMessage::argumentCount() const
+{
+ return m_arguments.size();
+}
+
+MessageType V8ConsoleMessage::type() const
+{
+ return m_type;
+}
+
+// static
+std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI(double timestampMS, MessageType type, MessageLevel level, const String16& messageText, protocol::Vector<v8::Local<v8::Value>>* arguments, std::unique_ptr<V8StackTrace> stackTrace, InspectedContext* context)
+{
+ String16 url;
+ unsigned lineNumber = 0;
+ unsigned columnNumber = 0;
+ if (stackTrace && !stackTrace->isEmpty()) {
+ url = stackTrace->topSourceURL();
+ lineNumber = stackTrace->topLineNumber();
+ columnNumber = stackTrace->topColumnNumber();
+ }
+
+ String16 actualMessage = messageText;
+
+ Arguments messageArguments;
+ if (arguments) {
kozy 2016/06/23 22:28:43 && arguments.size()
dgozman 2016/06/28 01:43:48 Done.
+ for (size_t i = 0; i < arguments->size(); ++i)
+ messageArguments.append(wrapUnique(new v8::Global<v8::Value>(context->isolate(), arguments->at(i))));
+ if (actualMessage.isEmpty() && messageArguments.size())
+ actualMessage = V8ValueStringBuilder::toString(messageArguments.at(0)->Get(context->isolate()), context->isolate());
+ }
+
+ std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(timestampMS, ConsoleAPIMessageSource, level, actualMessage, url, lineNumber, columnNumber, std::move(stackTrace), 0, String16()));
kozy 2016/06/23 22:28:43 0 /* scriptId */, String16() /* requestIdentifier
dgozman 2016/06/28 01:43:48 Done.
+ message->m_type = type;
+ if (messageArguments.size()) {
+ message->m_contextId = context->contextId();
+ message->m_arguments.swap(messageArguments);
+ }
+
+ context->debugger()->client()->messageAddedToConsole(context->contextGroupId(), message->m_source, message->m_level, message->m_message, message->m_url, message->m_lineNumber, message->m_columnNumber, message->m_stackTrace.get());
+ return message;
+}
+
+void V8ConsoleMessage::contextDestroyed(int contextId)
+{
+ if (contextId != m_contextId)
+ return;
+ m_contextId = 0;
+ if (m_message.isEmpty())
+ m_message = "<message collected>";
+ Arguments empty;
+ m_arguments.swap(empty);
+}
+
+void V8ConsoleMessage::assignId(unsigned id)
+{
+ m_messageId = id;
+}
+
+void V8ConsoleMessage::assignRelatedId(unsigned id)
+{
+ m_relatedMessageId = id;
+}
+
+void V8ConsoleMessage::addArguments(v8::Isolate* isolate, int contextId, protocol::Vector<v8::Local<v8::Value>>* arguments)
+{
+ if (!arguments || !contextId)
+ return;
+ m_contextId = contextId;
+ for (size_t i = 0; i < arguments->size(); ++i)
+ m_arguments.append(wrapUnique(new v8::Global<v8::Value>(isolate, arguments->at(i))));
+}
+
+// ------------------------ V8ConsoleMessageStorage ----------------------------
+
+V8ConsoleMessageStorage::V8ConsoleMessageStorage(V8DebuggerImpl* debugger, int contextGroupId)
+ : m_debugger(debugger)
+ , m_contextGroupId(contextGroupId)
+ , m_expiredCount(0)
+{
+}
+
+
kozy 2016/06/23 22:28:43 style: extra blank line
dgozman 2016/06/28 01:43:48 Done.
+V8ConsoleMessageStorage::~V8ConsoleMessageStorage()
+{
+ clear();
+}
+
+void V8ConsoleMessageStorage::addMessage(std::unique_ptr<V8ConsoleMessage> message)
+{
+ if (message->type() == ClearMessageType)
+ clear();
+
+ V8InspectorSessionImpl* session = m_debugger->sessionForContextGroup(m_contextGroupId);
+ if (session)
+ session->consoleAgent()->messageAdded(message.get());
+
+ DCHECK(m_messages.size() <= maxConsoleMessageCount);
+ if (m_messages.size() == maxConsoleMessageCount) {
+ ++m_expiredCount;
+ m_messages.pop_front();
+ }
+ m_messages.push_back(std::move(message));
+}
+
+void V8ConsoleMessageStorage::clear()
+{
+ m_messages.clear();
+ m_expiredCount = 0;
+ V8InspectorSessionImpl* session = m_debugger->sessionForContextGroup(m_contextGroupId);
+ if (session) {
+ session->consoleAgent()->reset();
+ session->releaseObjectGroup("console");
+ session->client()->consoleCleared();
+ }
+}
+
+void V8ConsoleMessageStorage::contextDestroyed(int contextId)
+{
+ for (size_t i = 0; i < m_messages.size(); ++i)
+ m_messages[i]->contextDestroyed(contextId);
+}
+
+protocol::Vector<unsigned> V8ConsoleMessageStorage::consoleMessageArgumentCounts()
+{
+ protocol::Vector<unsigned> result(m_messages.size());
+ for (size_t i = 0; i < m_messages.size(); ++i)
+ result[i] = m_messages[i]->argumentCount();
+ return result;
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698