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

Side by Side 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: improved api a bit Created 4 years, 5 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "platform/v8_inspector/V8ConsoleMessage.h"
6
7 #include "platform/v8_inspector/InspectedContext.h"
8 #include "platform/v8_inspector/V8ConsoleAgentImpl.h"
9 #include "platform/v8_inspector/V8DebuggerImpl.h"
10 #include "platform/v8_inspector/V8InspectorSessionImpl.h"
11 #include "platform/v8_inspector/V8StackTraceImpl.h"
12 #include "platform/v8_inspector/V8StringUtil.h"
13 #include "platform/v8_inspector/public/V8DebuggerClient.h"
14
15 namespace blink {
16
17 namespace {
18
19 String messageSourceValue(MessageSource source)
20 {
21 switch (source) {
22 case XMLMessageSource: return protocol::Console::ConsoleMessage::SourceEnum: :Xml;
23 case JSMessageSource: return protocol::Console::ConsoleMessage::SourceEnum:: Javascript;
24 case NetworkMessageSource: return protocol::Console::ConsoleMessage::SourceE num::Network;
25 case ConsoleAPIMessageSource: return protocol::Console::ConsoleMessage::Sour ceEnum::ConsoleApi;
26 case StorageMessageSource: return protocol::Console::ConsoleMessage::SourceE num::Storage;
27 case AppCacheMessageSource: return protocol::Console::ConsoleMessage::Source Enum::Appcache;
28 case RenderingMessageSource: return protocol::Console::ConsoleMessage::Sourc eEnum::Rendering;
29 case SecurityMessageSource: return protocol::Console::ConsoleMessage::Source Enum::Security;
30 case OtherMessageSource: return protocol::Console::ConsoleMessage::SourceEnu m::Other;
31 case DeprecationMessageSource: return protocol::Console::ConsoleMessage::Sou rceEnum::Deprecation;
32 }
33 return protocol::Console::ConsoleMessage::SourceEnum::Other;
34 }
35
36
37 String messageTypeValue(MessageType type)
38 {
39 switch (type) {
40 case LogMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Log ;
41 case ClearMessageType: return protocol::Console::ConsoleMessage::TypeEnum::C lear;
42 case DirMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Dir ;
43 case DirXMLMessageType: return protocol::Console::ConsoleMessage::TypeEnum:: Dirxml;
44 case TableMessageType: return protocol::Console::ConsoleMessage::TypeEnum::T able;
45 case TraceMessageType: return protocol::Console::ConsoleMessage::TypeEnum::T race;
46 case StartGroupMessageType: return protocol::Console::ConsoleMessage::TypeEn um::StartGroup;
47 case StartGroupCollapsedMessageType: return protocol::Console::ConsoleMessag e::TypeEnum::StartGroupCollapsed;
48 case EndGroupMessageType: return protocol::Console::ConsoleMessage::TypeEnum ::EndGroup;
49 case AssertMessageType: return protocol::Console::ConsoleMessage::TypeEnum:: Assert;
50 case TimeEndMessageType: return protocol::Console::ConsoleMessage::TypeEnum: :Log;
51 case CountMessageType: return protocol::Console::ConsoleMessage::TypeEnum::L og;
52 }
53 return protocol::Console::ConsoleMessage::TypeEnum::Log;
54 }
55
56 String messageLevelValue(MessageLevel level)
57 {
58 switch (level) {
59 case DebugMessageLevel: return protocol::Console::ConsoleMessage::LevelEnum: :Debug;
60 case LogMessageLevel: return protocol::Console::ConsoleMessage::LevelEnum::L og;
61 case WarningMessageLevel: return protocol::Console::ConsoleMessage::LevelEnu m::Warning;
62 case ErrorMessageLevel: return protocol::Console::ConsoleMessage::LevelEnum: :Error;
63 case InfoMessageLevel: return protocol::Console::ConsoleMessage::LevelEnum:: Info;
64 case RevokedErrorMessageLevel: return protocol::Console::ConsoleMessage::Lev elEnum::RevokedError;
65 }
66 return protocol::Console::ConsoleMessage::LevelEnum::Log;
67 }
68
69 const unsigned maxConsoleMessageCount = 1000;
70 const unsigned maxArrayItemsLimit = 10000;
71 const unsigned maxStackDepthLimit = 32;
72
73 class V8ValueStringBuilder {
74 public:
75 static String16 toString(v8::Local<v8::Value> value, v8::Isolate* isolate)
76 {
77 V8ValueStringBuilder builder(isolate);
78 if (!builder.append(value))
79 return String16();
80 return builder.toString();
81 }
82
83 private:
84 enum {
85 IgnoreNull = 1 << 0,
86 IgnoreUndefined = 1 << 1,
87 };
88
89 V8ValueStringBuilder(v8::Isolate* isolate)
90 : m_arrayLimit(maxArrayItemsLimit)
91 , m_isolate(isolate)
92 , m_tryCatch(isolate)
93 {
94 }
95
96 bool append(v8::Local<v8::Value> value, unsigned ignoreOptions = 0)
97 {
98 if (value.IsEmpty())
99 return true;
100 if ((ignoreOptions & IgnoreNull) && value->IsNull())
101 return true;
102 if ((ignoreOptions & IgnoreUndefined) && value->IsUndefined())
103 return true;
104 if (value->IsString())
105 return append(v8::Local<v8::String>::Cast(value));
106 if (value->IsStringObject())
107 return append(v8::Local<v8::StringObject>::Cast(value)->ValueOf());
108 if (value->IsSymbol())
109 return append(v8::Local<v8::Symbol>::Cast(value));
110 if (value->IsSymbolObject())
111 return append(v8::Local<v8::SymbolObject>::Cast(value)->ValueOf());
112 if (value->IsNumberObject()) {
113 m_builder.appendNumber(v8::Local<v8::NumberObject>::Cast(value)->Val ueOf());
114 return true;
115 }
116 if (value->IsBooleanObject()) {
117 m_builder.append(v8::Local<v8::BooleanObject>::Cast(value)->ValueOf( ) ? "true" : "false");
118 return true;
119 }
120 if (value->IsArray())
121 return append(v8::Local<v8::Array>::Cast(value));
122 if (value->IsProxy()) {
123 m_builder.append("[object Proxy]");
124 return true;
125 }
126 if (value->IsObject()
127 && !value->IsDate()
128 && !value->IsFunction()
129 && !value->IsNativeError()
130 && !value->IsRegExp()) {
131 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
132 v8::Local<v8::String> stringValue;
133 if (object->ObjectProtoToString(m_isolate->GetCurrentContext()).ToLo cal(&stringValue))
134 return append(stringValue);
135 }
136 v8::Local<v8::String> stringValue;
137 if (!value->ToString(m_isolate->GetCurrentContext()).ToLocal(&stringValu e))
138 return false;
139 return append(stringValue);
140 }
141
142 bool append(v8::Local<v8::Array> array)
143 {
144 if (m_visitedArrays.contains(array))
145 return true;
146 uint32_t length = array->Length();
147 if (length > m_arrayLimit)
148 return false;
149 if (m_visitedArrays.size() > maxStackDepthLimit)
150 return false;
151
152 bool result = true;
153 m_arrayLimit -= length;
154 m_visitedArrays.append(array);
155 for (uint32_t i = 0; i < length; ++i) {
156 if (i)
157 m_builder.append(',');
158 if (!append(array->Get(i), IgnoreNull | IgnoreUndefined)) {
159 result = false;
160 break;
161 }
162 }
163 m_visitedArrays.removeLast();
164 return result;
165 }
166
167 bool append(v8::Local<v8::Symbol> symbol)
168 {
169 m_builder.append("Symbol(");
170 bool result = append(symbol->Name(), IgnoreUndefined);
171 m_builder.append(')');
172 return result;
173 }
174
175 bool append(v8::Local<v8::String> string)
176 {
177 if (m_tryCatch.HasCaught())
178 return false;
179 if (!string.IsEmpty())
180 m_builder.append(toProtocolString(string));
181 return true;
182 }
183
184 String16 toString()
185 {
186 if (m_tryCatch.HasCaught())
187 return String16();
188 return m_builder.toString();
189 }
190
191 uint32_t m_arrayLimit;
192 v8::Isolate* m_isolate;
193 String16Builder m_builder;
194 Vector<v8::Local<v8::Array>> m_visitedArrays;
195 v8::TryCatch m_tryCatch;
196 };
197
198 } // namespace
199
200 V8ConsoleMessage::V8ConsoleMessage(
201 double timestampMS,
202 MessageSource source,
203 MessageLevel level,
204 const String16& message,
205 const String16& url,
206 unsigned lineNumber,
207 unsigned columnNumber,
208 std::unique_ptr<V8StackTrace> stackTrace,
209 int scriptId,
210 const String16& requestIdentifier)
211 : m_timestamp(timestampMS / 1000.0)
212 , m_source(source)
213 , m_level(level)
214 , m_message(message)
215 , m_url(url)
216 , m_lineNumber(lineNumber)
217 , m_columnNumber(columnNumber)
218 , m_stackTrace(std::move(stackTrace))
219 , m_scriptId(scriptId)
220 , m_requestIdentifier(requestIdentifier)
221 , m_contextId(0)
222 , m_type(LogMessageType)
223 , m_messageId(0)
224 , m_relatedMessageId(0)
225 {
226 }
227
228 V8ConsoleMessage::~V8ConsoleMessage()
229 {
230 }
231
232 std::unique_ptr<protocol::Console::ConsoleMessage> V8ConsoleMessage::buildInspec torObject(V8InspectorSessionImpl* session, bool generatePreview) const
233 {
234 std::unique_ptr<protocol::Console::ConsoleMessage> result =
235 protocol::Console::ConsoleMessage::create()
236 .setSource(messageSourceValue(m_source))
237 .setLevel(messageLevelValue(m_level))
238 .setText(m_message)
239 .setTimestamp(m_timestamp)
240 .build();
241 result->setType(messageTypeValue(m_type));
242 result->setLine(static_cast<int>(m_lineNumber));
243 result->setColumn(static_cast<int>(m_columnNumber));
244 if (m_scriptId)
245 result->setScriptId(String::number(m_scriptId));
246 result->setUrl(m_url);
247 if (m_source == NetworkMessageSource && !m_requestIdentifier.isEmpty())
248 result->setNetworkRequestId(m_requestIdentifier);
249 if (m_contextId)
250 result->setExecutionContextId(m_contextId);
251 appendArguments(result.get(), session, generatePreview);
252 if (m_stackTrace)
253 result->setStack(m_stackTrace->buildInspectorObject());
254 if (m_messageId)
255 result->setMessageId(m_messageId);
256 if (m_relatedMessageId)
257 result->setRelatedMessageId(m_relatedMessageId);
258 return result;
259 }
260
261 void V8ConsoleMessage::appendArguments(protocol::Console::ConsoleMessage* result , V8InspectorSessionImpl* session, bool generatePreview) const
262 {
263 if (!m_arguments.size() || !m_contextId)
264 return;
265 InspectedContext* inspectedContext = session->debugger()->getContext(session ->contextGroupId(), m_contextId);
266 if (!inspectedContext)
267 return;
268
269 v8::Isolate* isolate = inspectedContext->isolate();
270 v8::HandleScope handles(isolate);
271 v8::Local<v8::Context> context = inspectedContext->context();
272
273 std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>> args = pro tocol::Array<protocol::Runtime::RemoteObject>::create();
274 if (m_type == TableMessageType && generatePreview) {
275 v8::Local<v8::Value> table = m_arguments[0]->Get(isolate);
276 v8::Local<v8::Value> columns = m_arguments.size() > 1 ? m_arguments[1]-> Get(isolate) : v8::Local<v8::Value>();
277 std::unique_ptr<protocol::Runtime::RemoteObject> wrapped = session->wrap Table(context, table, columns);
278 if (wrapped)
279 args->addItem(std::move(wrapped));
280 else
281 args = nullptr;
282 } else {
283 for (size_t i = 0; i < m_arguments.size(); ++i) {
284 std::unique_ptr<protocol::Runtime::RemoteObject> wrapped = session-> wrapObject(context, m_arguments[i]->Get(isolate), "console", generatePreview);
285 if (!wrapped) {
286 args = nullptr;
287 break;
288 }
289 args->addItem(std::move(wrapped));
290 }
291 }
292 if (args)
293 result->setParameters(std::move(args));
294 }
295
296 unsigned V8ConsoleMessage::argumentCount() const
297 {
298 return m_arguments.size();
299 }
300
301 MessageType V8ConsoleMessage::type() const
302 {
303 return m_type;
304 }
305
306 // static
307 std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI(double t imestampMS, MessageType type, MessageLevel level, const String16& messageText, s td::vector<v8::Local<v8::Value>>* arguments, std::unique_ptr<V8StackTrace> stack Trace, InspectedContext* context)
308 {
309 String16 url;
310 unsigned lineNumber = 0;
311 unsigned columnNumber = 0;
312 if (stackTrace && !stackTrace->isEmpty()) {
313 url = stackTrace->topSourceURL();
314 lineNumber = stackTrace->topLineNumber();
315 columnNumber = stackTrace->topColumnNumber();
316 }
317
318 String16 actualMessage = messageText;
319
320 Arguments messageArguments;
321 if (arguments && arguments->size()) {
322 for (size_t i = 0; i < arguments->size(); ++i)
323 messageArguments.push_back(wrapUnique(new v8::Global<v8::Value>(cont ext->isolate(), arguments->at(i))));
324 if (actualMessage.isEmpty())
325 actualMessage = V8ValueStringBuilder::toString(messageArguments.at(0 )->Get(context->isolate()), context->isolate());
326 }
327
328 std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage( timestampMS, ConsoleAPIMessageSource, level, actualMessage, url, lineNumber, col umnNumber, std::move(stackTrace), 0 /* scriptId */, String16() /* requestIdentif ier */));
329 message->m_type = type;
330 if (messageArguments.size()) {
331 message->m_contextId = context->contextId();
332 message->m_arguments.swap(messageArguments);
333 }
334
335 context->debugger()->client()->messageAddedToConsole(context->contextGroupId (), message->m_source, message->m_level, message->m_message, message->m_url, mes sage->m_lineNumber, message->m_columnNumber, message->m_stackTrace.get());
336 return message;
337 }
338
339 void V8ConsoleMessage::contextDestroyed(int contextId)
340 {
341 if (contextId != m_contextId)
342 return;
343 m_contextId = 0;
344 if (m_message.isEmpty())
345 m_message = "<message collected>";
346 Arguments empty;
347 m_arguments.swap(empty);
348 }
349
350 void V8ConsoleMessage::assignId(unsigned id)
351 {
352 m_messageId = id;
353 }
354
355 void V8ConsoleMessage::assignRelatedId(unsigned id)
356 {
357 m_relatedMessageId = id;
358 }
359
360 void V8ConsoleMessage::addArguments(v8::Isolate* isolate, int contextId, std::ve ctor<v8::Local<v8::Value>>* arguments)
361 {
362 if (!arguments || !contextId)
363 return;
364 m_contextId = contextId;
365 for (size_t i = 0; i < arguments->size(); ++i)
366 m_arguments.push_back(wrapUnique(new v8::Global<v8::Value>(isolate, argu ments->at(i))));
367 }
368
369 // ------------------------ V8ConsoleMessageStorage ----------------------------
370
371 V8ConsoleMessageStorage::V8ConsoleMessageStorage(V8DebuggerImpl* debugger, int c ontextGroupId)
372 : m_debugger(debugger)
373 , m_contextGroupId(contextGroupId)
374 , m_expiredCount(0)
375 {
376 }
377
378 V8ConsoleMessageStorage::~V8ConsoleMessageStorage()
379 {
380 clear();
381 }
382
383 void V8ConsoleMessageStorage::addMessage(std::unique_ptr<V8ConsoleMessage> messa ge)
384 {
385 if (message->type() == ClearMessageType)
386 clear();
387
388 V8InspectorSessionImpl* session = m_debugger->sessionForContextGroup(m_conte xtGroupId);
389 if (session)
390 session->consoleAgent()->messageAdded(message.get());
391
392 DCHECK(m_messages.size() <= maxConsoleMessageCount);
393 if (m_messages.size() == maxConsoleMessageCount) {
394 ++m_expiredCount;
395 m_messages.pop_front();
396 }
397 m_messages.push_back(std::move(message));
398 }
399
400 void V8ConsoleMessageStorage::clear()
401 {
402 m_messages.clear();
403 m_expiredCount = 0;
404 V8InspectorSessionImpl* session = m_debugger->sessionForContextGroup(m_conte xtGroupId);
405 if (session) {
406 session->consoleAgent()->reset();
407 session->releaseObjectGroup("console");
408 session->client()->consoleCleared();
409 }
410 }
411
412 void V8ConsoleMessageStorage::contextDestroyed(int contextId)
413 {
414 for (size_t i = 0; i < m_messages.size(); ++i)
415 m_messages[i]->contextDestroyed(contextId);
416 }
417
418 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698