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 "ConsoleAPITypes.h" 35#include "ConsoleTypes.h" 36#include "Document.h" 37#include "Frame.h" 38#include "FrameLoader.h" 39#include "FrameTree.h" 40#include "InspectorConsoleInstrumentation.h" 41#include "InspectorController.h" 42#include "Page.h" 43#include "PageConsole.h" 44#include "PageGroup.h" 45#include "ScriptArguments.h" 46#include "ScriptCallStack.h" 47#include "ScriptCallStackFactory.h" 48#include "ScriptProfile.h" 49#include "ScriptProfiler.h" 50#include "ScriptValue.h" 51#include "ScriptableDocumentParser.h" 52#include "Settings.h" 53#include <stdio.h> 54#include <wtf/text/CString.h> 55#include <wtf/text/WTFString.h> 56 57namespace WebCore { 58 59Console::Console(Frame* frame) 60 : DOMWindowProperty(frame) 61{ 62} 63 64Console::~Console() 65{ 66} 67 68static void internalAddMessage(Page* page, MessageType type, MessageLevel level, ScriptState* state, PassRefPtr<ScriptArguments> prpArguments, bool acceptNoArguments = false, bool printTrace = false) 69{ 70 RefPtr<ScriptArguments> arguments = prpArguments; 71 72 if (!page) 73 return; 74 75 if (!acceptNoArguments && !arguments->argumentCount()) 76 return; 77 78 size_t stackSize = printTrace ? ScriptCallStack::maxCallStackSizeToCapture : 1; 79 RefPtr<ScriptCallStack> callStack(createScriptCallStack(state, stackSize)); 80 const ScriptCallFrame& lastCaller = callStack->at(0); 81 82 String message; 83 bool gotMessage = arguments->getFirstArgumentAsString(message); 84 InspectorInstrumentation::addMessageToConsole(page, ConsoleAPIMessageSource, type, level, message, state, arguments); 85 86 if (page->settings()->privateBrowsingEnabled()) 87 return; 88 89 if (gotMessage) 90 page->chrome().client()->addMessageToConsole(ConsoleAPIMessageSource, type, level, message, lastCaller.lineNumber(), lastCaller.columnNumber(), lastCaller.sourceURL()); 91 92 if (!page->settings()->logsPageMessagesToSystemConsoleEnabled() && !PageConsole::shouldPrintExceptions()) 93 return; 94 95 PageConsole::printSourceURLAndLine(lastCaller.sourceURL(), lastCaller.lineNumber()); 96 PageConsole::printMessageSourceAndLevelPrefix(ConsoleAPIMessageSource, level); 97 98 for (size_t i = 0; i < arguments->argumentCount(); ++i) { 99 String argAsString = arguments->argumentAt(i).toString(arguments->globalState()); 100 printf(" %s", argAsString.utf8().data()); 101 } 102 103 printf("\n"); 104 105 if (printTrace) { 106 printf("Stack Trace\n"); 107 for (size_t i = 0; i < callStack->size(); ++i) { 108 String functionName = String(callStack->at(i).functionName()); 109 printf("\t%s\n", functionName.utf8().data()); 110 } 111 } 112} 113 114void Console::debug(ScriptState* state, PassRefPtr<ScriptArguments> arguments) 115{ 116 internalAddMessage(page(), LogMessageType, DebugMessageLevel, state, arguments); 117} 118 119void Console::error(ScriptState* state, PassRefPtr<ScriptArguments> arguments) 120{ 121 internalAddMessage(page(), LogMessageType, ErrorMessageLevel, state, arguments); 122} 123 124void Console::info(ScriptState* state, PassRefPtr<ScriptArguments> arguments) 125{ 126 log(state, arguments); 127} 128 129void Console::log(ScriptState* state, PassRefPtr<ScriptArguments> arguments) 130{ 131 internalAddMessage(page(), LogMessageType, LogMessageLevel, state, arguments); 132} 133 134void Console::warn(ScriptState* state, PassRefPtr<ScriptArguments> arguments) 135{ 136 internalAddMessage(page(), LogMessageType, WarningMessageLevel, state, arguments); 137} 138 139void Console::dir(ScriptState* state, PassRefPtr<ScriptArguments> arguments) 140{ 141 internalAddMessage(page(), DirMessageType, LogMessageLevel, state, arguments); 142} 143 144void Console::dirxml(ScriptState* state, PassRefPtr<ScriptArguments> arguments) 145{ 146 internalAddMessage(page(), DirXMLMessageType, LogMessageLevel, state, arguments); 147} 148 149void Console::table(ScriptState* state, PassRefPtr<ScriptArguments> arguments) 150{ 151 internalAddMessage(page(), TableMessageType, LogMessageLevel, state, arguments); 152} 153 154void Console::clear(ScriptState* state, PassRefPtr<ScriptArguments> arguments) 155{ 156 internalAddMessage(page(), ClearMessageType, LogMessageLevel, state, arguments, true); 157} 158 159void Console::trace(ScriptState* state, PassRefPtr<ScriptArguments> arguments) 160{ 161 internalAddMessage(page(), TraceMessageType, LogMessageLevel, state, arguments, true, true); 162} 163 164void Console::assertCondition(ScriptState* state, PassRefPtr<ScriptArguments> arguments, bool condition) 165{ 166 if (condition) 167 return; 168 169 internalAddMessage(page(), AssertMessageType, ErrorMessageLevel, state, arguments, true); 170} 171 172void Console::count(ScriptState* state, PassRefPtr<ScriptArguments> arguments) 173{ 174 InspectorInstrumentation::consoleCount(page(), state, arguments); 175} 176 177#if ENABLE(JAVASCRIPT_DEBUGGER) 178 179void Console::profile(const String& title, ScriptState* state) 180{ 181 Page* page = this->page(); 182 if (!page) 183 return; 184 185 // FIXME: log a console message when profiling is disabled. 186 if (!InspectorInstrumentation::profilerEnabled(page)) 187 return; 188 189 String resolvedTitle = title; 190 if (title.isNull()) // no title so give it the next user initiated profile title. 191 resolvedTitle = InspectorInstrumentation::getCurrentUserInitiatedProfileName(page, true); 192 193 ScriptProfiler::start(state, resolvedTitle); 194 195 RefPtr<ScriptCallStack> callStack(createScriptCallStack(state, 1)); 196 const ScriptCallFrame& lastCaller = callStack->at(0); 197 InspectorInstrumentation::addStartProfilingMessageToConsole(page, resolvedTitle, lastCaller.lineNumber(), lastCaller.columnNumber(), lastCaller.sourceURL()); 198} 199 200void Console::profileEnd(const String& title, ScriptState* state) 201{ 202 Page* page = this->page(); 203 if (!page) 204 return; 205 206 if (!InspectorInstrumentation::profilerEnabled(page)) 207 return; 208 209 RefPtr<ScriptProfile> profile = ScriptProfiler::stop(state, title); 210 if (!profile) 211 return; 212 213 m_profiles.append(profile); 214 RefPtr<ScriptCallStack> callStack(createScriptCallStack(state, 1)); 215 InspectorInstrumentation::addProfile(page, profile, callStack); 216} 217 218#endif 219 220void Console::time(const String& title) 221{ 222 InspectorInstrumentation::startConsoleTiming(m_frame, title); 223} 224 225void Console::timeEnd(ScriptState* state, const String& title) 226{ 227 RefPtr<ScriptCallStack> callStack(createScriptCallStackForConsole(state)); 228 InspectorInstrumentation::stopConsoleTiming(m_frame, title, callStack.release()); 229} 230 231void Console::timeStamp(PassRefPtr<ScriptArguments> arguments) 232{ 233 InspectorInstrumentation::consoleTimeStamp(m_frame, arguments); 234} 235 236void Console::group(ScriptState* state, PassRefPtr<ScriptArguments> arguments) 237{ 238 InspectorInstrumentation::addMessageToConsole(page(), ConsoleAPIMessageSource, StartGroupMessageType, LogMessageLevel, String(), state, arguments); 239} 240 241void Console::groupCollapsed(ScriptState* state, PassRefPtr<ScriptArguments> arguments) 242{ 243 InspectorInstrumentation::addMessageToConsole(page(), ConsoleAPIMessageSource, StartGroupCollapsedMessageType, LogMessageLevel, String(), state, arguments); 244} 245 246void Console::groupEnd() 247{ 248 InspectorInstrumentation::addMessageToConsole(page(), ConsoleAPIMessageSource, EndGroupMessageType, LogMessageLevel, String(), String(), 0, 0); 249} 250 251Page* Console::page() const 252{ 253 if (!m_frame) 254 return 0; 255 return m_frame->page(); 256} 257 258} // namespace WebCore 259