]>
Commit | Line | Data |
---|---|---|
81345200 A |
1 | /* |
2 | * Copyright (C) 2007, 2008, 2014 Apple Inc. All rights reserved. | |
3 | * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> | |
4 | * Copyright (C) 2009, 2010 Google Inc. All rights reserved. | |
5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | |
9 | * | |
10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | |
15 | * 3. Neither the name of Apple Inc. ("Apple") nor the names of | |
16 | * its contributors may be used to endorse or promote products derived | |
17 | * from this software without specific prior written permission. | |
18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | |
20 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
22 | * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | |
23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
26 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
28 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 | */ | |
30 | ||
31 | #include "config.h" | |
32 | #include "ConsoleMessage.h" | |
33 | ||
81345200 A |
34 | #include "IdentifiersFactory.h" |
35 | #include "InjectedScript.h" | |
36 | #include "InjectedScriptManager.h" | |
37 | #include "InspectorValues.h" | |
38 | #include "ScriptArguments.h" | |
39 | #include "ScriptCallFrame.h" | |
40 | #include "ScriptCallStack.h" | |
41 | #include "ScriptCallStackFactory.h" | |
42 | #include "ScriptValue.h" | |
43 | ||
44 | namespace Inspector { | |
45 | ||
46 | ConsoleMessage::ConsoleMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned long requestIdentifier) | |
47 | : m_source(source) | |
48 | , m_type(type) | |
49 | , m_level(level) | |
50 | , m_message(message) | |
51 | , m_url() | |
52 | , m_line(0) | |
53 | , m_column(0) | |
54 | , m_repeatCount(1) | |
55 | , m_requestId(IdentifiersFactory::requestId(requestIdentifier)) | |
56 | { | |
57 | } | |
58 | ||
59 | ConsoleMessage::ConsoleMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, const String& url, unsigned line, unsigned column, JSC::ExecState* state, unsigned long requestIdentifier) | |
60 | : m_source(source) | |
61 | , m_type(type) | |
62 | , m_level(level) | |
63 | , m_message(message) | |
64 | , m_url(url) | |
65 | , m_line(line) | |
66 | , m_column(column) | |
67 | , m_repeatCount(1) | |
68 | , m_requestId(IdentifiersFactory::requestId(requestIdentifier)) | |
69 | { | |
70 | autogenerateMetadata(state); | |
71 | } | |
72 | ||
73 | ConsoleMessage::ConsoleMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptCallStack> callStack, unsigned long requestIdentifier) | |
74 | : m_source(source) | |
75 | , m_type(type) | |
76 | , m_level(level) | |
77 | , m_message(message) | |
78 | , m_url() | |
79 | , m_line(0) | |
80 | , m_column(0) | |
81 | , m_repeatCount(1) | |
82 | , m_requestId(IdentifiersFactory::requestId(requestIdentifier)) | |
83 | { | |
84 | m_callStack = callStack; | |
85 | ||
86 | const ScriptCallFrame* frame = m_callStack ? m_callStack->firstNonNativeCallFrame() : nullptr; | |
87 | if (frame) { | |
88 | m_url = frame->sourceURL(); | |
89 | m_line = frame->lineNumber(); | |
90 | m_column = frame->columnNumber(); | |
91 | } | |
92 | } | |
93 | ||
94 | ConsoleMessage::ConsoleMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptArguments> arguments, JSC::ExecState* state, unsigned long requestIdentifier) | |
95 | : m_source(source) | |
96 | , m_type(type) | |
97 | , m_level(level) | |
98 | , m_message(message) | |
99 | , m_arguments(arguments) | |
100 | , m_url() | |
101 | , m_line(0) | |
102 | , m_column(0) | |
103 | , m_repeatCount(1) | |
104 | , m_requestId(IdentifiersFactory::requestId(requestIdentifier)) | |
105 | { | |
106 | autogenerateMetadata(state); | |
107 | } | |
108 | ||
109 | ConsoleMessage::~ConsoleMessage() | |
110 | { | |
111 | } | |
112 | ||
113 | void ConsoleMessage::autogenerateMetadata(JSC::ExecState* state) | |
114 | { | |
115 | if (!state) | |
116 | return; | |
117 | ||
118 | if (m_type == MessageType::EndGroup) | |
119 | return; | |
120 | ||
121 | // FIXME: Should this really be using "for console" in the generic ConsoleMessage autogeneration? This can skip the first frame. | |
122 | m_callStack = createScriptCallStackForConsole(state, ScriptCallStack::maxCallStackSizeToCapture); | |
123 | ||
124 | if (const ScriptCallFrame* frame = m_callStack->firstNonNativeCallFrame()) { | |
125 | m_url = frame->sourceURL(); | |
126 | m_line = frame->lineNumber(); | |
127 | m_column = frame->columnNumber(); | |
128 | return; | |
129 | } | |
130 | } | |
131 | ||
ed1e77d3 | 132 | static Inspector::Protocol::Console::ConsoleMessage::Source messageSourceValue(MessageSource source) |
81345200 A |
133 | { |
134 | switch (source) { | |
ed1e77d3 A |
135 | case MessageSource::XML: return Inspector::Protocol::Console::ConsoleMessage::Source::XML; |
136 | case MessageSource::JS: return Inspector::Protocol::Console::ConsoleMessage::Source::Javascript; | |
137 | case MessageSource::Network: return Inspector::Protocol::Console::ConsoleMessage::Source::Network; | |
138 | case MessageSource::ConsoleAPI: return Inspector::Protocol::Console::ConsoleMessage::Source::ConsoleAPI; | |
139 | case MessageSource::Storage: return Inspector::Protocol::Console::ConsoleMessage::Source::Storage; | |
140 | case MessageSource::AppCache: return Inspector::Protocol::Console::ConsoleMessage::Source::Appcache; | |
141 | case MessageSource::Rendering: return Inspector::Protocol::Console::ConsoleMessage::Source::Rendering; | |
142 | case MessageSource::CSS: return Inspector::Protocol::Console::ConsoleMessage::Source::CSS; | |
143 | case MessageSource::Security: return Inspector::Protocol::Console::ConsoleMessage::Source::Security; | |
144 | case MessageSource::ContentBlocker: return Inspector::Protocol::Console::ConsoleMessage::Source::ContentBlocker; | |
145 | case MessageSource::Other: return Inspector::Protocol::Console::ConsoleMessage::Source::Other; | |
81345200 | 146 | } |
ed1e77d3 | 147 | return Inspector::Protocol::Console::ConsoleMessage::Source::Other; |
81345200 A |
148 | } |
149 | ||
ed1e77d3 | 150 | static Inspector::Protocol::Console::ConsoleMessage::Type messageTypeValue(MessageType type) |
81345200 A |
151 | { |
152 | switch (type) { | |
ed1e77d3 A |
153 | case MessageType::Log: return Inspector::Protocol::Console::ConsoleMessage::Type::Log; |
154 | case MessageType::Clear: return Inspector::Protocol::Console::ConsoleMessage::Type::Clear; | |
155 | case MessageType::Dir: return Inspector::Protocol::Console::ConsoleMessage::Type::Dir; | |
156 | case MessageType::DirXML: return Inspector::Protocol::Console::ConsoleMessage::Type::DirXML; | |
157 | case MessageType::Table: return Inspector::Protocol::Console::ConsoleMessage::Type::Table; | |
158 | case MessageType::Trace: return Inspector::Protocol::Console::ConsoleMessage::Type::Trace; | |
159 | case MessageType::StartGroup: return Inspector::Protocol::Console::ConsoleMessage::Type::StartGroup; | |
160 | case MessageType::StartGroupCollapsed: return Inspector::Protocol::Console::ConsoleMessage::Type::StartGroupCollapsed; | |
161 | case MessageType::EndGroup: return Inspector::Protocol::Console::ConsoleMessage::Type::EndGroup; | |
162 | case MessageType::Assert: return Inspector::Protocol::Console::ConsoleMessage::Type::Assert; | |
163 | case MessageType::Timing: return Inspector::Protocol::Console::ConsoleMessage::Type::Timing; | |
164 | case MessageType::Profile: return Inspector::Protocol::Console::ConsoleMessage::Type::Profile; | |
165 | case MessageType::ProfileEnd: return Inspector::Protocol::Console::ConsoleMessage::Type::ProfileEnd; | |
81345200 | 166 | } |
ed1e77d3 | 167 | return Inspector::Protocol::Console::ConsoleMessage::Type::Log; |
81345200 A |
168 | } |
169 | ||
ed1e77d3 | 170 | static Inspector::Protocol::Console::ConsoleMessage::Level messageLevelValue(MessageLevel level) |
81345200 A |
171 | { |
172 | switch (level) { | |
ed1e77d3 A |
173 | case MessageLevel::Log: return Inspector::Protocol::Console::ConsoleMessage::Level::Log; |
174 | case MessageLevel::Info: return Inspector::Protocol::Console::ConsoleMessage::Level::Info; | |
175 | case MessageLevel::Warning: return Inspector::Protocol::Console::ConsoleMessage::Level::Warning; | |
176 | case MessageLevel::Error: return Inspector::Protocol::Console::ConsoleMessage::Level::Error; | |
177 | case MessageLevel::Debug: return Inspector::Protocol::Console::ConsoleMessage::Level::Debug; | |
81345200 | 178 | } |
ed1e77d3 | 179 | return Inspector::Protocol::Console::ConsoleMessage::Level::Log; |
81345200 A |
180 | } |
181 | ||
ed1e77d3 | 182 | void ConsoleMessage::addToFrontend(ConsoleFrontendDispatcher* consoleFrontendDispatcher, InjectedScriptManager* injectedScriptManager, bool generatePreview) |
81345200 | 183 | { |
ed1e77d3 | 184 | Ref<Inspector::Protocol::Console::ConsoleMessage> jsonObj = Inspector::Protocol::Console::ConsoleMessage::create() |
81345200 A |
185 | .setSource(messageSourceValue(m_source)) |
186 | .setLevel(messageLevelValue(m_level)) | |
ed1e77d3 A |
187 | .setText(m_message) |
188 | .release(); | |
81345200 A |
189 | |
190 | // FIXME: only send out type for ConsoleAPI source messages. | |
191 | jsonObj->setType(messageTypeValue(m_type)); | |
192 | jsonObj->setLine(static_cast<int>(m_line)); | |
193 | jsonObj->setColumn(static_cast<int>(m_column)); | |
194 | jsonObj->setUrl(m_url); | |
195 | jsonObj->setRepeatCount(static_cast<int>(m_repeatCount)); | |
196 | ||
197 | if (m_source == MessageSource::Network && !m_requestId.isEmpty()) | |
198 | jsonObj->setNetworkRequestId(m_requestId); | |
199 | ||
200 | if (m_arguments && m_arguments->argumentCount()) { | |
201 | InjectedScript injectedScript = injectedScriptManager->injectedScriptFor(m_arguments->globalState()); | |
202 | if (!injectedScript.hasNoValue()) { | |
ed1e77d3 | 203 | Ref<Inspector::Protocol::Array<Inspector::Protocol::Runtime::RemoteObject>> jsonArgs = Inspector::Protocol::Array<Inspector::Protocol::Runtime::RemoteObject>::create(); |
81345200 A |
204 | if (m_type == MessageType::Table && generatePreview && m_arguments->argumentCount()) { |
205 | Deprecated::ScriptValue table = m_arguments->argumentAt(0); | |
206 | Deprecated::ScriptValue columns = m_arguments->argumentCount() > 1 ? m_arguments->argumentAt(1) : Deprecated::ScriptValue(); | |
ed1e77d3 | 207 | RefPtr<Inspector::Protocol::Runtime::RemoteObject> inspectorValue = injectedScript.wrapTable(table, columns); |
81345200 A |
208 | if (!inspectorValue) { |
209 | ASSERT_NOT_REACHED(); | |
210 | return; | |
211 | } | |
ed1e77d3 A |
212 | jsonArgs->addItem(inspectorValue.copyRef()); |
213 | if (m_arguments->argumentCount() > 1) | |
214 | jsonArgs->addItem(injectedScript.wrapObject(columns, ASCIILiteral("console"), true)); | |
81345200 A |
215 | } else { |
216 | for (unsigned i = 0; i < m_arguments->argumentCount(); ++i) { | |
ed1e77d3 | 217 | RefPtr<Inspector::Protocol::Runtime::RemoteObject> inspectorValue = injectedScript.wrapObject(m_arguments->argumentAt(i), ASCIILiteral("console"), generatePreview); |
81345200 A |
218 | if (!inspectorValue) { |
219 | ASSERT_NOT_REACHED(); | |
220 | return; | |
221 | } | |
ed1e77d3 | 222 | jsonArgs->addItem(inspectorValue.copyRef()); |
81345200 A |
223 | } |
224 | } | |
ed1e77d3 | 225 | jsonObj->setParameters(WTF::move(jsonArgs)); |
81345200 A |
226 | } |
227 | } | |
228 | ||
229 | if (m_callStack) | |
230 | jsonObj->setStackTrace(m_callStack->buildInspectorArray()); | |
231 | ||
ed1e77d3 | 232 | consoleFrontendDispatcher->messageAdded(WTF::move(jsonObj)); |
81345200 A |
233 | } |
234 | ||
ed1e77d3 | 235 | void ConsoleMessage::updateRepeatCountInConsole(ConsoleFrontendDispatcher* consoleFrontendDispatcher) |
81345200 A |
236 | { |
237 | consoleFrontendDispatcher->messageRepeatCountUpdated(m_repeatCount); | |
238 | } | |
239 | ||
240 | bool ConsoleMessage::isEqual(ConsoleMessage* msg) const | |
241 | { | |
242 | if (m_arguments) { | |
243 | if (!m_arguments->isEqual(msg->m_arguments.get())) | |
244 | return false; | |
245 | ||
246 | // Never treat objects as equal - their properties might change over time. | |
247 | for (size_t i = 0; i < m_arguments->argumentCount(); ++i) { | |
248 | if (m_arguments->argumentAt(i).isObject()) | |
249 | return false; | |
250 | } | |
251 | } else if (msg->m_arguments) | |
252 | return false; | |
253 | ||
254 | if (m_callStack) { | |
255 | if (!m_callStack->isEqual(msg->m_callStack.get())) | |
256 | return false; | |
257 | } else if (msg->m_callStack) | |
258 | return false; | |
259 | ||
260 | return msg->m_source == m_source | |
261 | && msg->m_type == m_type | |
262 | && msg->m_level == m_level | |
263 | && msg->m_message == m_message | |
264 | && msg->m_line == m_line | |
265 | && msg->m_column == m_column | |
266 | && msg->m_url == m_url | |
267 | && msg->m_requestId == m_requestId; | |
268 | } | |
269 | ||
270 | void ConsoleMessage::clear() | |
271 | { | |
272 | if (!m_message) | |
273 | m_message = ASCIILiteral("<message collected>"); | |
274 | ||
275 | if (m_arguments) | |
ed1e77d3 | 276 | m_arguments = nullptr; |
81345200 A |
277 | } |
278 | ||
279 | JSC::ExecState* ConsoleMessage::scriptState() const | |
280 | { | |
281 | if (m_arguments) | |
282 | return m_arguments->globalState(); | |
283 | ||
284 | return nullptr; | |
285 | } | |
286 | ||
287 | unsigned ConsoleMessage::argumentCount() const | |
288 | { | |
289 | if (m_arguments) | |
290 | return m_arguments->argumentCount(); | |
291 | ||
292 | return 0; | |
293 | } | |
294 | ||
295 | } // namespace Inspector |