Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / inspector / InspectorConsoleAgent.cpp
1 /*
2  * Copyright (C) 2011 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
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25
26 #include "config.h"
27 #include "core/inspector/InspectorConsoleAgent.h"
28
29 #include "bindings/core/v8/ScriptCallStackFactory.h"
30 #include "bindings/core/v8/ScriptController.h"
31 #include "bindings/core/v8/ScriptProfiler.h"
32 #include "core/frame/LocalFrame.h"
33 #include "core/frame/UseCounter.h"
34 #include "core/inspector/ConsoleMessage.h"
35 #include "core/inspector/ConsoleMessageStorage.h"
36 #include "core/inspector/IdentifiersFactory.h"
37 #include "core/inspector/InjectedScript.h"
38 #include "core/inspector/InjectedScriptHost.h"
39 #include "core/inspector/InjectedScriptManager.h"
40 #include "core/inspector/InspectorState.h"
41 #include "core/inspector/InspectorTimelineAgent.h"
42 #include "core/inspector/InstrumentingAgents.h"
43 #include "core/inspector/ScriptArguments.h"
44 #include "core/inspector/ScriptAsyncCallStack.h"
45 #include "core/inspector/ScriptCallFrame.h"
46 #include "core/inspector/ScriptCallStack.h"
47 #include "core/loader/DocumentLoader.h"
48 #include "core/page/Page.h"
49 #include "core/xmlhttprequest/XMLHttpRequest.h"
50 #include "platform/network/ResourceError.h"
51 #include "platform/network/ResourceResponse.h"
52 #include "wtf/CurrentTime.h"
53 #include "wtf/OwnPtr.h"
54 #include "wtf/PassOwnPtr.h"
55 #include "wtf/text/StringBuilder.h"
56 #include "wtf/text/WTFString.h"
57
58 namespace blink {
59
60 namespace ConsoleAgentState {
61 static const char monitoringXHR[] = "monitoringXHR";
62 static const char consoleMessagesEnabled[] = "consoleMessagesEnabled";
63 static const char tracingBasedTimeline[] = "tracingBasedTimeline";
64 }
65
66 int InspectorConsoleAgent::s_enabledAgentCount = 0;
67
68 InspectorConsoleAgent::InspectorConsoleAgent(InspectorTimelineAgent* timelineAgent, InjectedScriptManager* injectedScriptManager)
69     : InspectorBaseAgent<InspectorConsoleAgent>("Console")
70     , m_timelineAgent(timelineAgent)
71     , m_injectedScriptManager(injectedScriptManager)
72     , m_frontend(0)
73     , m_enabled(false)
74 {
75 }
76
77 InspectorConsoleAgent::~InspectorConsoleAgent()
78 {
79 #if !ENABLE(OILPAN)
80     m_instrumentingAgents->setInspectorConsoleAgent(0);
81 #endif
82 }
83
84 void InspectorConsoleAgent::trace(Visitor* visitor)
85 {
86     visitor->trace(m_timelineAgent);
87     visitor->trace(m_injectedScriptManager);
88     InspectorBaseAgent::trace(visitor);
89 }
90
91 void InspectorConsoleAgent::enable(ErrorString*)
92 {
93     if (m_enabled)
94         return;
95     m_instrumentingAgents->setInspectorConsoleAgent(this);
96     m_enabled = true;
97     if (!s_enabledAgentCount)
98         ScriptController::setCaptureCallStackForUncaughtExceptions(true);
99     ++s_enabledAgentCount;
100
101     m_state->setBoolean(ConsoleAgentState::consoleMessagesEnabled, true);
102
103     ConsoleMessageStorage* storage = messageStorage();
104     if (storage->expiredCount()) {
105         RefPtrWillBeRawPtr<ConsoleMessage> expiredMessage = ConsoleMessage::create(OtherMessageSource, WarningMessageLevel, String::format("%d console messages are not shown.", storage->expiredCount()));
106         expiredMessage->setTimestamp(0);
107         sendConsoleMessageToFrontend(expiredMessage.get(), false);
108     }
109
110     size_t messageCount = storage->size();
111     for (size_t i = 0; i < messageCount; ++i)
112         sendConsoleMessageToFrontend(storage->at(i), false);
113 }
114
115 void InspectorConsoleAgent::disable(ErrorString*)
116 {
117     if (!m_enabled)
118         return;
119     m_instrumentingAgents->setInspectorConsoleAgent(0);
120     m_enabled = false;
121     if (!(--s_enabledAgentCount))
122         ScriptController::setCaptureCallStackForUncaughtExceptions(false);
123     m_state->setBoolean(ConsoleAgentState::consoleMessagesEnabled, false);
124     m_state->setBoolean(ConsoleAgentState::tracingBasedTimeline, false);
125 }
126
127 void InspectorConsoleAgent::clearMessages(ErrorString*)
128 {
129     messageStorage()->clear();
130 }
131
132 void InspectorConsoleAgent::restore()
133 {
134     if (m_state->getBoolean(ConsoleAgentState::consoleMessagesEnabled)) {
135         m_frontend->messagesCleared();
136         ErrorString error;
137         enable(&error);
138     }
139 }
140
141 void InspectorConsoleAgent::setFrontend(InspectorFrontend* frontend)
142 {
143     m_frontend = frontend->console();
144 }
145
146 void InspectorConsoleAgent::clearFrontend()
147 {
148     m_frontend = 0;
149     String errorString;
150     disable(&errorString);
151 }
152
153 void InspectorConsoleAgent::addMessageToConsole(ConsoleMessage* consoleMessage)
154 {
155     if (m_frontend)
156         sendConsoleMessageToFrontend(consoleMessage, true);
157 }
158
159 void InspectorConsoleAgent::consoleMessagesCleared()
160 {
161     m_injectedScriptManager->releaseObjectGroup("console");
162     if (m_frontend)
163         m_frontend->messagesCleared();
164 }
165
166 void InspectorConsoleAgent::setTracingBasedTimeline(ErrorString*, bool enabled)
167 {
168     m_state->setBoolean(ConsoleAgentState::tracingBasedTimeline, enabled);
169 }
170
171 void InspectorConsoleAgent::consoleTimeline(ExecutionContext* context, const String& title, ScriptState* scriptState)
172 {
173     UseCounter::count(context, UseCounter::DevToolsConsoleTimeline);
174     if (!m_state->getBoolean(ConsoleAgentState::tracingBasedTimeline))
175         m_timelineAgent->consoleTimeline(context, title, scriptState);
176 }
177
178 void InspectorConsoleAgent::consoleTimelineEnd(ExecutionContext* context, const String& title, ScriptState* scriptState)
179 {
180     if (!m_state->getBoolean(ConsoleAgentState::tracingBasedTimeline))
181         m_timelineAgent->consoleTimelineEnd(context, title, scriptState);
182 }
183
184 void InspectorConsoleAgent::didFinishXHRLoading(XMLHttpRequest*, ThreadableLoaderClient*, unsigned long requestIdentifier, ScriptString, const AtomicString& method, const String& url)
185 {
186     if (m_frontend && m_state->getBoolean(ConsoleAgentState::monitoringXHR)) {
187         String message = "XHR finished loading: " + method + " \"" + url + "\".";
188         RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(NetworkMessageSource, DebugMessageLevel, message);
189         consoleMessage->setRequestIdentifier(requestIdentifier);
190         messageStorage()->reportMessage(consoleMessage.release());
191     }
192 }
193
194 void InspectorConsoleAgent::setMonitoringXHREnabled(ErrorString*, bool enabled)
195 {
196     m_state->setBoolean(ConsoleAgentState::monitoringXHR, enabled);
197 }
198
199 static TypeBuilder::Console::ConsoleMessage::Source::Enum messageSourceValue(MessageSource source)
200 {
201     switch (source) {
202     case XMLMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Xml;
203     case JSMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Javascript;
204     case NetworkMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Network;
205     case ConsoleAPIMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Console_api;
206     case StorageMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Storage;
207     case AppCacheMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Appcache;
208     case RenderingMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Rendering;
209     case CSSMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Css;
210     case SecurityMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Security;
211     case OtherMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Other;
212     case DeprecationMessageSource: return TypeBuilder::Console::ConsoleMessage::Source::Deprecation;
213     }
214     return TypeBuilder::Console::ConsoleMessage::Source::Other;
215 }
216
217
218 static TypeBuilder::Console::ConsoleMessage::Type::Enum messageTypeValue(MessageType type)
219 {
220     switch (type) {
221     case LogMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Log;
222     case ClearMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Clear;
223     case DirMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Dir;
224     case DirXMLMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Dirxml;
225     case TableMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Table;
226     case TraceMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Trace;
227     case StartGroupMessageType: return TypeBuilder::Console::ConsoleMessage::Type::StartGroup;
228     case StartGroupCollapsedMessageType: return TypeBuilder::Console::ConsoleMessage::Type::StartGroupCollapsed;
229     case EndGroupMessageType: return TypeBuilder::Console::ConsoleMessage::Type::EndGroup;
230     case AssertMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Assert;
231     case TimeEndMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Log;
232     case CountMessageType: return TypeBuilder::Console::ConsoleMessage::Type::Log;
233     }
234     return TypeBuilder::Console::ConsoleMessage::Type::Log;
235 }
236
237 static TypeBuilder::Console::ConsoleMessage::Level::Enum messageLevelValue(MessageLevel level)
238 {
239     switch (level) {
240     case DebugMessageLevel: return TypeBuilder::Console::ConsoleMessage::Level::Debug;
241     case LogMessageLevel: return TypeBuilder::Console::ConsoleMessage::Level::Log;
242     case WarningMessageLevel: return TypeBuilder::Console::ConsoleMessage::Level::Warning;
243     case ErrorMessageLevel: return TypeBuilder::Console::ConsoleMessage::Level::Error;
244     case InfoMessageLevel: return TypeBuilder::Console::ConsoleMessage::Level::Info;
245     }
246     return TypeBuilder::Console::ConsoleMessage::Level::Log;
247 }
248
249 void InspectorConsoleAgent::sendConsoleMessageToFrontend(ConsoleMessage* consoleMessage, bool generatePreview)
250 {
251     if (consoleMessage->workerGlobalScopeProxy())
252         return;
253
254     RefPtr<TypeBuilder::Console::ConsoleMessage> jsonObj = TypeBuilder::Console::ConsoleMessage::create()
255         .setSource(messageSourceValue(consoleMessage->source()))
256         .setLevel(messageLevelValue(consoleMessage->level()))
257         .setText(consoleMessage->message())
258         .setTimestamp(consoleMessage->timestamp());
259     // FIXME: only send out type for ConsoleAPI source messages.
260     jsonObj->setType(messageTypeValue(consoleMessage->type()));
261     jsonObj->setLine(static_cast<int>(consoleMessage->lineNumber()));
262     jsonObj->setColumn(static_cast<int>(consoleMessage->columnNumber()));
263     if (consoleMessage->scriptId())
264         jsonObj->setScriptId(String::number(consoleMessage->scriptId()));
265     jsonObj->setUrl(consoleMessage->url());
266     ScriptState* scriptState = consoleMessage->scriptState();
267     if (scriptState)
268         jsonObj->setExecutionContextId(m_injectedScriptManager->injectedScriptIdFor(scriptState));
269     if (consoleMessage->source() == NetworkMessageSource && consoleMessage->requestIdentifier())
270         jsonObj->setNetworkRequestId(IdentifiersFactory::requestId(consoleMessage->requestIdentifier()));
271     RefPtrWillBeRawPtr<ScriptArguments> arguments = consoleMessage->scriptArguments();
272     if (arguments && arguments->argumentCount()) {
273         InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(arguments->scriptState());
274         if (!injectedScript.isEmpty()) {
275             RefPtr<TypeBuilder::Array<TypeBuilder::Runtime::RemoteObject> > jsonArgs = TypeBuilder::Array<TypeBuilder::Runtime::RemoteObject>::create();
276             if (consoleMessage->type() == TableMessageType && generatePreview && arguments->argumentCount()) {
277                 ScriptValue table = arguments->argumentAt(0);
278                 ScriptValue columns = arguments->argumentCount() > 1 ? arguments->argumentAt(1) : ScriptValue();
279                 RefPtr<TypeBuilder::Runtime::RemoteObject> inspectorValue = injectedScript.wrapTable(table, columns);
280                 if (!inspectorValue) {
281                     ASSERT_NOT_REACHED();
282                     return;
283                 }
284                 jsonArgs->addItem(inspectorValue);
285             } else {
286                 for (unsigned i = 0; i < arguments->argumentCount(); ++i) {
287                     RefPtr<TypeBuilder::Runtime::RemoteObject> inspectorValue = injectedScript.wrapObject(arguments->argumentAt(i), "console", generatePreview);
288                     if (!inspectorValue) {
289                         ASSERT_NOT_REACHED();
290                         return;
291                     }
292                     jsonArgs->addItem(inspectorValue);
293                 }
294             }
295             jsonObj->setParameters(jsonArgs);
296         }
297     }
298     if (consoleMessage->callStack()) {
299         jsonObj->setStackTrace(consoleMessage->callStack()->buildInspectorArray());
300         RefPtrWillBeRawPtr<ScriptAsyncCallStack> asyncCallStack = consoleMessage->callStack()->asyncCallStack();
301         if (asyncCallStack)
302             jsonObj->setAsyncStackTrace(asyncCallStack->buildInspectorObject());
303     }
304     m_frontend->messageAdded(jsonObj);
305     m_frontend->flush();
306 }
307
308 class InspectableHeapObject final : public InjectedScriptHost::InspectableObject {
309 public:
310     explicit InspectableHeapObject(int heapObjectId) : m_heapObjectId(heapObjectId) { }
311     virtual ScriptValue get(ScriptState*) override
312     {
313         return ScriptProfiler::objectByHeapObjectId(m_heapObjectId);
314     }
315 private:
316     int m_heapObjectId;
317 };
318
319 void InspectorConsoleAgent::addInspectedHeapObject(ErrorString*, int inspectedHeapObjectId)
320 {
321     m_injectedScriptManager->injectedScriptHost()->addInspectedObject(adoptPtr(new InspectableHeapObject(inspectedHeapObjectId)));
322 }
323
324 void InspectorConsoleAgent::setLastEvaluationResult(ErrorString* errorString, const String& objectId)
325 {
326     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
327     if (injectedScript.isEmpty()) {
328         *errorString = "Inspected frame has gone";
329         return;
330     }
331     injectedScript.setLastEvaluationResult(objectId);
332 }
333
334 } // namespace blink