Merge "WebProcess crash is occured during changing default directory path for file...
[framework/web/webkit-efl.git] / Source / WebCore / page / Console.cpp
1 /*
2  * Copyright (C) 2007 Apple 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "Console.h"
31
32 #include "Chrome.h"
33 #include "ChromeClient.h"
34 #include "Frame.h"
35 #include "FrameLoader.h"
36 #include "FrameTree.h"
37 #include "InspectorConsoleInstrumentation.h"
38 #include "InspectorController.h"
39 #include "MemoryInfo.h"
40 #include "Page.h"
41 #include "PageGroup.h"
42 #include "PlatformString.h"
43 #include "ScriptArguments.h"
44 #include "ScriptCallStack.h"
45 #include "ScriptProfile.h"
46 #include "ScriptProfiler.h"
47 #include "ScriptValue.h"
48 #include <stdio.h>
49 #include <wtf/UnusedParam.h>
50 #include <wtf/text/CString.h>
51
52 #if PLATFORM(CHROMIUM)
53 #include "TraceEvent.h"
54 #endif
55
56 namespace WebCore {
57
58 namespace {
59     int muteCount = 0;
60 }
61
62 Console::Console(Frame* frame)
63     : DOMWindowProperty(frame)
64 {
65 }
66
67 Console::~Console()
68 {
69 }
70
71 static void printSourceURLAndLine(const String& sourceURL, unsigned lineNumber)
72 {
73     if (!sourceURL.isEmpty()) {
74         if (lineNumber > 0)
75             printf("%s:%d: ", sourceURL.utf8().data(), lineNumber);
76         else
77             printf("%s: ", sourceURL.utf8().data());
78     }
79 }
80
81 static void printMessageSourceAndLevelPrefix(MessageSource source, MessageLevel level)
82 {
83     const char* sourceString;
84     switch (source) {
85     case HTMLMessageSource:
86         sourceString = "HTML";
87         break;
88     case XMLMessageSource:
89         sourceString = "XML";
90         break;
91     case JSMessageSource:
92         sourceString = "JS";
93         break;
94     case NetworkMessageSource:
95         sourceString = "NETWORK";
96         break;
97     case ConsoleAPIMessageSource:
98         sourceString = "CONSOLEAPI";
99         break;
100     case OtherMessageSource:
101         sourceString = "OTHER";
102         break;
103     default:
104         ASSERT_NOT_REACHED();
105         sourceString = "UNKNOWN";
106         break;
107     }
108
109     const char* levelString;
110     switch (level) {
111     case TipMessageLevel:
112         levelString = "TIP";
113         break;
114     case LogMessageLevel:
115         levelString = "LOG";
116         break;
117     case WarningMessageLevel:
118         levelString = "WARN";
119         break;
120     case ErrorMessageLevel:
121         levelString = "ERROR";
122         break;
123     case DebugMessageLevel:
124         levelString = "DEBUG";
125         break;
126     default:
127         ASSERT_NOT_REACHED();
128         levelString = "UNKNOWN";
129         break;
130     }
131
132     printf("%s %s:", sourceString, levelString);
133 }
134
135 void Console::addMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, PassRefPtr<ScriptCallStack> callStack)
136 {
137     addMessage(source, type, level, message, String(), 0, callStack);
138 }
139
140 void Console::addMessage(MessageSource source, MessageType type, MessageLevel level, const String& message, const String& sourceURL, unsigned lineNumber, PassRefPtr<ScriptCallStack> callStack)
141 {
142
143     if (muteCount && source != ConsoleAPIMessageSource)
144         return;
145
146     Page* page = this->page();
147     if (!page)
148         return;
149
150     page->chrome()->client()->addMessageToConsole(source, type, level, message, lineNumber, sourceURL);
151
152     if (callStack)
153         InspectorInstrumentation::addMessageToConsole(page, source, type, level, message, 0, callStack);
154     else
155         InspectorInstrumentation::addMessageToConsole(page, source, type, level, message, sourceURL, lineNumber);
156
157     if (!Console::shouldPrintExceptions())
158         return;
159
160     printSourceURLAndLine(sourceURL, lineNumber);
161     printMessageSourceAndLevelPrefix(source, level);
162
163     printf(" %s\n", message.utf8().data());
164 }
165
166 void Console::addMessage(MessageType type, MessageLevel level, PassRefPtr<ScriptArguments> prpArguments,  PassRefPtr<ScriptCallStack> prpCallStack, bool acceptNoArguments)
167 {
168     RefPtr<ScriptArguments> arguments = prpArguments;
169     RefPtr<ScriptCallStack> callStack = prpCallStack;
170
171     Page* page = this->page();
172     if (!page)
173         return;
174
175     const ScriptCallFrame& lastCaller = callStack->at(0);
176
177     if (!acceptNoArguments && !arguments->argumentCount())
178         return;
179
180     if (Console::shouldPrintExceptions()) {
181         printSourceURLAndLine(lastCaller.sourceURL(), 0);
182         printMessageSourceAndLevelPrefix(ConsoleAPIMessageSource, level);
183
184         for (unsigned i = 0; i < arguments->argumentCount(); ++i) {
185             String argAsString;
186             if (arguments->argumentAt(i).getString(arguments->globalState(), argAsString))
187                 printf(" %s", argAsString.utf8().data());
188         }
189         printf("\n");
190     }
191
192     String message;
193     if (arguments->getFirstArgumentAsString(message))
194         page->chrome()->client()->addMessageToConsole(ConsoleAPIMessageSource, type, level, message, lastCaller.lineNumber(), lastCaller.sourceURL());
195
196     InspectorInstrumentation::addMessageToConsole(page, ConsoleAPIMessageSource, type, level, message, arguments, callStack);
197 }
198
199 void Console::debug(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
200 {
201 #if ENABLE(TIZEN_DISPLAY_MESSAGE_TO_CONSOLE)
202     addMessage(LogMessageType, LogMessageLevel, arguments, callStack);
203     return;
204 #endif
205     // In Firebug, console.debug has the same behavior as console.log. So we'll do the same.
206     log(arguments, callStack);
207 }
208
209 void Console::error(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
210 {
211     addMessage(LogMessageType, ErrorMessageLevel, arguments, callStack);
212 }
213
214 void Console::info(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
215 {
216     log(arguments, callStack);
217 }
218
219 void Console::log(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
220 {
221     addMessage(LogMessageType, LogMessageLevel, arguments, callStack);
222 }
223
224 void Console::warn(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
225 {
226     addMessage(LogMessageType, WarningMessageLevel, arguments, callStack);
227 }
228
229 void Console::dir(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
230 {
231     addMessage(DirMessageType, LogMessageLevel, arguments, callStack);
232 }
233
234 void Console::dirxml(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
235 {
236     addMessage(DirXMLMessageType, LogMessageLevel, arguments, callStack);
237 }
238
239 void Console::trace(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> prpCallStack)
240 {
241     RefPtr<ScriptCallStack> callStack = prpCallStack;
242     addMessage(TraceMessageType, LogMessageLevel, arguments, callStack, true);
243
244     if (!shouldPrintExceptions())
245         return;
246
247     printf("Stack Trace\n");
248     for (unsigned i = 0; i < callStack->size(); ++i) {
249         String functionName = String(callStack->at(i).functionName());
250         printf("\t%s\n", functionName.utf8().data());
251     }
252 }
253
254 void Console::assertCondition(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack, bool condition)
255 {
256     if (condition)
257         return;
258
259     addMessage(AssertMessageType, ErrorMessageLevel, arguments, callStack, true);
260 }
261
262 void Console::count(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
263 {
264     InspectorInstrumentation::consoleCount(page(), arguments, callStack);
265 }
266
267 void Console::markTimeline(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack>)
268 {
269     InspectorInstrumentation::consoleTimeStamp(page(), arguments);
270 }
271
272 #if ENABLE(JAVASCRIPT_DEBUGGER)
273
274 void Console::profile(const String& title, ScriptState* state, PassRefPtr<ScriptCallStack> callStack)
275 {
276     Page* page = this->page();
277     if (!page)
278         return;
279
280     // FIXME: log a console message when profiling is disabled.
281     if (!InspectorInstrumentation::profilerEnabled(page))
282         return;
283
284     String resolvedTitle = title;
285     if (title.isNull()) // no title so give it the next user initiated profile title.
286         resolvedTitle = InspectorInstrumentation::getCurrentUserInitiatedProfileName(page, true);
287
288     ScriptProfiler::start(state, resolvedTitle);
289
290     const ScriptCallFrame& lastCaller = callStack->at(0);
291     InspectorInstrumentation::addStartProfilingMessageToConsole(page, resolvedTitle, lastCaller.lineNumber(), lastCaller.sourceURL());
292 }
293
294 void Console::profileEnd(const String& title, ScriptState* state, PassRefPtr<ScriptCallStack> callStack)
295 {
296     Page* page = this->page();
297     if (!page)
298         return;
299
300     if (!InspectorInstrumentation::profilerEnabled(page))
301         return;
302
303     RefPtr<ScriptProfile> profile = ScriptProfiler::stop(state, title);
304     if (!profile)
305         return;
306
307     m_profiles.append(profile);
308     InspectorInstrumentation::addProfile(page, profile, callStack);
309 }
310
311 #endif
312
313 void Console::time(const String& title)
314 {
315     InspectorInstrumentation::startConsoleTiming(page(), title);
316 #if PLATFORM(CHROMIUM)
317     TRACE_EVENT_COPY_ASYNC_BEGIN0("webkit", title.utf8().data(), this);
318 #endif
319 }
320
321 void Console::timeEnd(PassRefPtr<ScriptArguments>, PassRefPtr<ScriptCallStack> callStack, const String& title)
322 {
323 #if PLATFORM(CHROMIUM)
324     TRACE_EVENT_COPY_ASYNC_END0("webkit", title.utf8().data(), this);
325 #endif
326     InspectorInstrumentation::stopConsoleTiming(page(), title, callStack);
327 }
328
329 void Console::timeStamp(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack>)
330 {
331     InspectorInstrumentation::consoleTimeStamp(page(), arguments);
332 }
333
334 void Console::group(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
335 {
336     InspectorInstrumentation::addMessageToConsole(page(), ConsoleAPIMessageSource, StartGroupMessageType, LogMessageLevel, String(), arguments, callStack);
337 }
338
339 void Console::groupCollapsed(PassRefPtr<ScriptArguments> arguments, PassRefPtr<ScriptCallStack> callStack)
340 {
341     InspectorInstrumentation::addMessageToConsole(page(), ConsoleAPIMessageSource, StartGroupCollapsedMessageType, LogMessageLevel, String(), arguments, callStack);
342 }
343
344 void Console::groupEnd()
345 {
346     InspectorInstrumentation::addMessageToConsole(page(), ConsoleAPIMessageSource, EndGroupMessageType, LogMessageLevel, String(), String(), 0);
347 }
348
349 // static
350 void Console::mute()
351 {
352     muteCount++;
353 }
354
355 // static
356 void Console::unmute()
357 {
358     ASSERT(muteCount > 0);
359     muteCount--;
360 }
361
362 PassRefPtr<MemoryInfo> Console::memory() const
363 {
364     // FIXME: Because we create a new object here each time,
365     // console.memory !== console.memory, which seems wrong.
366     return MemoryInfo::create(m_frame);
367 }
368
369 static bool printExceptions = false;
370
371 bool Console::shouldPrintExceptions()
372 {
373     return printExceptions;
374 }
375
376 void Console::setShouldPrintExceptions(bool print)
377 {
378     printExceptions = print;
379 }
380
381 Page* Console::page() const
382 {
383     if (!m_frame)
384         return 0;
385     return m_frame->page();
386 }
387
388 } // namespace WebCore