bc1db419c3ec7cae2f57b616e1334d443eaeb65a
[WebKit-https.git] / 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 "ChromeClient.h"
33 #include "CString.h"
34 #include "Frame.h"
35 #include "FrameLoader.h"
36 #include "FrameTree.h"
37 #include "InspectorController.h"
38 #include "Page.h"
39 #include "PageGroup.h"
40 #include "PlatformString.h"
41 #include <kjs/ArgList.h>
42 #include <kjs/interpreter.h>
43 #include <kjs/JSObject.h>
44 #include <profiler/Profile.h>
45 #include <stdio.h>
46
47 using namespace KJS;
48
49 namespace WebCore {
50
51 Console::Console(Frame* frame)
52     : m_frame(frame)
53 {
54 }
55
56 void Console::disconnectFrame()
57 {
58     m_frame = 0;
59 }
60
61 static void printSourceURLAndLine(const String& sourceURL, unsigned lineNumber)
62 {
63     if (!sourceURL.isEmpty()) {
64         if (lineNumber > 0)
65             printf("%s:%d: ", sourceURL.utf8().data(), lineNumber);
66         else
67             printf("%s: ", sourceURL.utf8().data());
68     }
69 }
70
71 static void printMessageSourceAndLevelPrefix(MessageSource source, MessageLevel level)
72 {
73     const char* sourceString;
74     switch (source) {
75         case HTMLMessageSource:
76             sourceString = "HTML";
77             break;
78         case XMLMessageSource:
79             sourceString = "XML";
80             break;
81         case JSMessageSource:
82             sourceString = "JS";
83             break;
84         case CSSMessageSource:
85             sourceString = "CSS";
86             break;
87         default:
88             ASSERT_NOT_REACHED();
89             // Fall thru.
90         case OtherMessageSource:
91             sourceString = "OTHER";
92             break;
93     }
94
95     const char* levelString;
96     switch (level) {
97         case TipMessageLevel:
98             levelString = "TIP";
99             break;
100         default:
101             ASSERT_NOT_REACHED();
102             // Fall thru.
103         case LogMessageLevel:
104             levelString = "LOG";
105             break;
106         case WarningMessageLevel:
107             levelString = "WARN";
108             break;
109         case ErrorMessageLevel:
110             levelString = "ERROR";
111             break;
112     }
113
114     printf("%s %s:", sourceString, levelString);
115 }
116
117 static void printToStandardOut(MessageSource source, MessageLevel level, const String& message, const String& sourceURL, unsigned lineNumber)
118 {
119     if (!Interpreter::shouldPrintExceptions())
120         return;
121
122     printSourceURLAndLine(sourceURL, lineNumber);
123     printMessageSourceAndLevelPrefix(source, level);
124
125     printf(" %s\n", message.utf8().data());
126 }
127
128 static void printToStandardOut(MessageLevel level, ExecState* exec, const ArgList& args, const KURL& url)
129 {
130     if (!Interpreter::shouldPrintExceptions())
131         return;
132
133     printSourceURLAndLine(url.prettyURL(), 0);
134     printMessageSourceAndLevelPrefix(JSMessageSource, level);
135
136     for (size_t i = 0; i < args.size(); ++i) {
137         UString argAsString = args.at(exec, i)->toString(exec);
138         printf(" %s", argAsString.UTF8String().c_str());
139     }
140
141     printf("\n");
142 }
143
144 void Console::addMessage(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL)
145 {
146     if (!m_frame)
147         return;
148
149     Page* page = m_frame->page();
150     if (!page)
151         return;
152
153     if (source == JSMessageSource)
154         page->chrome()->client()->addMessageToConsole(message, lineNumber, sourceURL);
155
156     page->inspectorController()->addMessageToConsole(source, level, message, lineNumber, sourceURL);
157
158     printToStandardOut(source, level, message, sourceURL, lineNumber);
159 }
160
161 void Console::debug(ExecState* exec, const ArgList& args)
162 {
163     // In Firebug, console.debug has the same behavior as console.log. So we'll do the same.
164     log(exec, args);
165 }
166
167 void Console::error(ExecState* exec, const ArgList& args)
168 {
169     if (args.isEmpty())
170         return;
171
172     if (!m_frame)
173         return;
174
175     Page* page = m_frame->page();
176     if (!page)
177         return;
178
179     String message = args.at(exec, 0)->toString(exec);
180     const KURL& url = m_frame->loader()->url();
181     String prettyURL = url.prettyURL();
182
183     page->chrome()->client()->addMessageToConsole(message, 0, prettyURL);
184     page->inspectorController()->addMessageToConsole(JSMessageSource, ErrorMessageLevel, exec, args, 0, url.string());
185
186     printToStandardOut(ErrorMessageLevel, exec, args, url);
187 }
188
189 void Console::info(ExecState* exec, const ArgList& args)
190 {
191     if (args.isEmpty())
192         return;
193
194     if (!m_frame)
195         return;
196
197     Page* page = m_frame->page();
198     if (!page)
199         return;
200
201     String message = args.at(exec, 0)->toString(exec);
202     const KURL& url = m_frame->loader()->url();
203     String prettyURL = url.prettyURL();
204
205     page->chrome()->client()->addMessageToConsole(message, 0, prettyURL);
206     page->inspectorController()->addMessageToConsole(JSMessageSource, LogMessageLevel, exec, args, 0, url.string());
207
208     printToStandardOut(LogMessageLevel, exec, args, url);
209 }
210
211 void Console::log(ExecState* exec, const ArgList& args)
212 {
213     if (args.isEmpty())
214         return;
215
216     if (!m_frame)
217         return;
218
219     Page* page = m_frame->page();
220     if (!page)
221         return;
222
223     String message = args.at(exec, 0)->toString(exec);
224     const KURL& url = m_frame->loader()->url();
225     String prettyURL = url.prettyURL();
226
227     page->chrome()->client()->addMessageToConsole(message, 0, prettyURL);
228     page->inspectorController()->addMessageToConsole(JSMessageSource, LogMessageLevel, exec, args, 0, url.string());
229
230     printToStandardOut(LogMessageLevel, exec, args, url);
231 }
232
233 void Console::assertCondition(bool condition, ExecState* exec, const ArgList& args)
234 {
235     if (condition)
236         return;
237
238     if (!m_frame)
239         return;
240
241     Page* page = m_frame->page();
242     if (!page)
243         return;
244
245     const KURL& url = m_frame->loader()->url();
246
247     // FIXME: <https://bugs.webkit.org/show_bug.cgi?id=19135> It would be nice to prefix assertion failures with a message like "Assertion failed: ".
248     // FIXME: <https://bugs.webkit.org/show_bug.cgi?id=19136> We should print a message even when args.isEmpty() is true.
249
250     page->inspectorController()->addMessageToConsole(JSMessageSource, ErrorMessageLevel, exec, args, 0, url.string());
251
252     printToStandardOut(ErrorMessageLevel, exec, args, url);
253 }
254
255 void Console::profile(ExecState* exec, const ArgList& args)
256 {
257     UString title = args.at(exec, 0)->toString(exec);
258     Profiler::profiler()->startProfiling(exec, title, this);
259 }
260
261 void Console::profileEnd(ExecState* exec, const ArgList& args)
262 {
263     UString title;
264     if (args.size() >= 1)
265         title = args.at(exec, 0)->toString(exec);
266
267     Profiler::profiler()->stopProfiling(exec, title);
268 }
269
270 void Console::finishedProfiling(PassRefPtr<Profile> prpProfile)
271 {
272     if (Page* page = m_frame->page())
273         page->inspectorController()->addProfile(prpProfile);
274 }
275
276 void Console::warn(ExecState* exec, const ArgList& args)
277 {
278     if (args.isEmpty())
279         return;
280
281     if (!m_frame)
282         return;
283
284     Page* page = m_frame->page();
285     if (!page)
286         return;
287
288     String message = args.at(exec, 0)->toString(exec);
289     const KURL& url = m_frame->loader()->url();
290     String prettyURL = url.prettyURL();
291
292     page->chrome()->client()->addMessageToConsole(message, 0, prettyURL);
293     page->inspectorController()->addMessageToConsole(JSMessageSource, WarningMessageLevel, exec, args, 0, url.string());
294
295     printToStandardOut(WarningMessageLevel, exec, args, url);
296 }
297
298 void Console::reportException(ExecState* exec, JSValue* exception)
299 {
300     UString errorMessage = exception->toString(exec);
301     JSObject* exceptionObject = exception->toObject(exec);
302     int lineNumber = exceptionObject->get(exec, Identifier(exec, "line"))->toInt32(exec);
303     UString exceptionSourceURL = exceptionObject->get(exec, Identifier(exec, "sourceURL"))->toString(exec);
304     addMessage(JSMessageSource, ErrorMessageLevel, errorMessage, lineNumber, exceptionSourceURL);
305 }
306
307 void Console::reportCurrentException(ExecState* exec)
308 {
309     JSValue* exception = exec->exception();
310     exec->clearException();
311     reportException(exec, exception);
312 }
313
314 } // namespace WebCore