2  * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 
   4  * Redistribution and use in source and binary forms, with or without 
   5  * modification, are permitted provided that the following conditions 
   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. 
  13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 
  14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR 
  17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
  19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
  21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
  22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
  23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  27 #include "ConsoleClient.h" 
  29 #include "ScriptArguments.h" 
  30 #include "ScriptCallStack.h" 
  31 #include "ScriptCallStackFactory.h" 
  32 #include "ScriptValue.h" 
  33 #include <wtf/Assertions.h> 
  34 #include <wtf/text/CString.h> 
  35 #include <wtf/text/StringBuilder.h> 
  36 #include <wtf/text/WTFString.h> 
  38 using namespace Inspector
; 
  42 static void appendURLAndPosition(StringBuilder
& builder
, const String
& url
, unsigned lineNumber
, unsigned columnNumber
) 
  51         builder
.appendNumber(lineNumber
); 
  54     if (columnNumber 
> 0) { 
  56         builder
.appendNumber(columnNumber
); 
  60 static void appendMessagePrefix(StringBuilder
& builder
, MessageSource source
, MessageType type
, MessageLevel level
) 
  62     const char* sourceString
; 
  64     case MessageSource::XML
: 
  67     case MessageSource::JS
: 
  70     case MessageSource::Network
: 
  71         sourceString 
= "NETWORK"; 
  73     case MessageSource::ConsoleAPI
: 
  74         sourceString 
= "CONSOLE"; 
  76     case MessageSource::Storage
: 
  77         sourceString 
= "STORAGE"; 
  79     case MessageSource::AppCache
: 
  80         sourceString 
= "APPCACHE"; 
  82     case MessageSource::Rendering
: 
  83         sourceString 
= "RENDERING"; 
  85     case MessageSource::CSS
: 
  88     case MessageSource::Security
: 
  89         sourceString 
= "SECURITY"; 
  91     case MessageSource::Other
: 
  92         sourceString 
= "OTHER"; 
  96         sourceString 
= "UNKNOWN"; 
 100     const char* levelString
; 
 102     case MessageLevel::Debug
: 
 103         levelString 
= "DEBUG"; 
 105     case MessageLevel::Log
: 
 108     case MessageLevel::Warning
: 
 109         levelString 
= "WARN"; 
 111     case MessageLevel::Error
: 
 112         levelString 
= "ERROR"; 
 115         ASSERT_NOT_REACHED(); 
 116         levelString 
= "UNKNOWN"; 
 120     if (type 
== MessageType::Trace
) 
 121         levelString 
= "TRACE"; 
 123     builder
.append(sourceString
); 
 125     builder
.append(levelString
); 
 128 void ConsoleClient::printConsoleMessage(MessageSource source
, MessageType type
, MessageLevel level
, const String
& message
, const String
& url
, unsigned lineNumber
, unsigned columnNumber
) 
 130     StringBuilder builder
; 
 132     if (!url
.isEmpty()) { 
 133         appendURLAndPosition(builder
, url
, lineNumber
, columnNumber
); 
 134         builder
.appendLiteral(": "); 
 137     appendMessagePrefix(builder
, source
, type
, level
); 
 139     builder
.append(message
); 
 141     WTFLogAlways("%s", builder
.toString().utf8().data()); 
 144 void ConsoleClient::printConsoleMessageWithArguments(MessageSource source
, MessageType type
, MessageLevel level
, JSC::ExecState
* exec
, PassRefPtr
<ScriptArguments
> prpArguments
) 
 146     RefPtr
<ScriptArguments
> arguments 
= prpArguments
; 
 148     bool isTraceMessage 
= type 
== MessageType::Trace
; 
 149     size_t stackSize 
= isTraceMessage 
? ScriptCallStack::maxCallStackSizeToCapture 
: 1; 
 150     RefPtr
<ScriptCallStack
> callStack(createScriptCallStackForConsole(exec
, stackSize
)); 
 151     const ScriptCallFrame
& lastCaller 
= callStack
->at(0); 
 153     StringBuilder builder
; 
 155     if (!lastCaller
.sourceURL().isEmpty()) { 
 156         appendURLAndPosition(builder
, lastCaller
.sourceURL(), lastCaller
.lineNumber(), lastCaller
.columnNumber()); 
 157         builder
.appendLiteral(": "); 
 160     appendMessagePrefix(builder
, source
, type
, level
); 
 161     for (size_t i 
= 0; i 
< arguments
->argumentCount(); ++i
) { 
 162         String argAsString 
= arguments
->argumentAt(i
).toString(arguments
->globalState()); 
 164         builder
.append(argAsString
.utf8().data()); 
 167     WTFLogAlways("%s", builder
.toString().utf8().data()); 
 169     if (isTraceMessage
) { 
 170         for (size_t i 
= 0; i 
< callStack
->size(); ++i
) { 
 171             const ScriptCallFrame
& callFrame 
= callStack
->at(i
); 
 172             String functionName 
= String(callFrame
.functionName()); 
 173             if (functionName
.isEmpty()) 
 174                 functionName 
= ASCIILiteral("(unknown)"); 
 176             StringBuilder callFrameBuilder
; 
 177             callFrameBuilder
.appendNumber(static_cast<unsigned long>(i
)); 
 178             callFrameBuilder
.appendLiteral(": "); 
 179             callFrameBuilder
.append(functionName
); 
 180             callFrameBuilder
.append('('); 
 181             appendURLAndPosition(callFrameBuilder
, callFrame
.sourceURL(), callFrame
.lineNumber(), callFrame
.columnNumber()); 
 182             callFrameBuilder
.append(')'); 
 184             WTFLogAlways("%s", callFrameBuilder
.toString().utf8().data()); 
 189 void ConsoleClient::internalMessageWithTypeAndLevel(MessageType type
, MessageLevel level
, JSC::ExecState
* exec
, PassRefPtr
<ScriptArguments
> prpArguments
, ArgumentRequirement argumentRequirement
) 
 191     RefPtr
<ScriptArguments
> arguments 
= prpArguments
; 
 192     if (argumentRequirement 
== ArgumentRequired 
&& !arguments
->argumentCount()) 
 195     messageWithTypeAndLevel(type
, level
, exec
, arguments
.release()); 
 198 void ConsoleClient::logWithLevel(ExecState
* exec
, PassRefPtr
<ScriptArguments
> arguments
, MessageLevel level
) 
 200     internalMessageWithTypeAndLevel(MessageType::Log
, level
, exec
, arguments
, ArgumentRequired
); 
 203 void ConsoleClient::clear(ExecState
* exec
, PassRefPtr
<ScriptArguments
> arguments
) 
 205     internalMessageWithTypeAndLevel(MessageType::Clear
, MessageLevel::Log
, exec
, arguments
, ArgumentNotRequired
); 
 208 void ConsoleClient::dir(ExecState
* exec
, PassRefPtr
<ScriptArguments
> arguments
) 
 210     internalMessageWithTypeAndLevel(MessageType::Dir
, MessageLevel::Log
, exec
, arguments
, ArgumentRequired
); 
 213 void ConsoleClient::dirXML(ExecState
* exec
, PassRefPtr
<ScriptArguments
> arguments
) 
 215     internalMessageWithTypeAndLevel(MessageType::DirXML
, MessageLevel::Log
, exec
, arguments
, ArgumentRequired
); 
 218 void ConsoleClient::table(ExecState
* exec
, PassRefPtr
<ScriptArguments
> arguments
) 
 220     internalMessageWithTypeAndLevel(MessageType::Table
, MessageLevel::Log
, exec
, arguments
, ArgumentRequired
); 
 223 void ConsoleClient::trace(ExecState
* exec
, PassRefPtr
<ScriptArguments
> arguments
) 
 225     internalMessageWithTypeAndLevel(MessageType::Trace
, MessageLevel::Log
, exec
, arguments
, ArgumentNotRequired
); 
 228 void ConsoleClient::assertCondition(ExecState
* exec
, PassRefPtr
<ScriptArguments
> arguments
, bool condition
) 
 233     internalMessageWithTypeAndLevel(MessageType::Assert
, MessageLevel::Error
, exec
, arguments
, ArgumentNotRequired
); 
 236 void ConsoleClient::group(ExecState
* exec
, PassRefPtr
<ScriptArguments
> arguments
) 
 238     internalMessageWithTypeAndLevel(MessageType::StartGroup
, MessageLevel::Log
, exec
, arguments
, ArgumentNotRequired
); 
 241 void ConsoleClient::groupCollapsed(ExecState
* exec
, PassRefPtr
<ScriptArguments
> arguments
) 
 243     internalMessageWithTypeAndLevel(MessageType::StartGroupCollapsed
, MessageLevel::Log
, exec
, arguments
, ArgumentNotRequired
); 
 246 void ConsoleClient::groupEnd(ExecState
* exec
, PassRefPtr
<ScriptArguments
> arguments
) 
 248     internalMessageWithTypeAndLevel(MessageType::EndGroup
, MessageLevel::Log
, exec
, arguments
, ArgumentNotRequired
);