9d5eb0b69630b8f5476bccf80549ea8620707f79
[WebKit-https.git] / Source / WebCore / inspector / agents / WebConsoleAgent.cpp
1 /*
2  * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
3  * Copyright (C) 2011 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26
27 #include "config.h"
28 #include "WebConsoleAgent.h"
29
30 #include "CommandLineAPIHost.h"
31 #include "DOMWindow.h"
32 #include "Logging.h"
33 #include "ResourceError.h"
34 #include "ResourceResponse.h"
35 #include "ScriptState.h"
36 #include "WebInjectedScriptManager.h"
37 #include <JavaScriptCore/ConsoleMessage.h>
38 #include <JavaScriptCore/JSCInlines.h>
39 #include <wtf/text/StringBuilder.h>
40
41
42 namespace WebCore {
43
44 using namespace Inspector;
45
46 WebConsoleAgent::WebConsoleAgent(AgentContext& context, InspectorHeapAgent* heapAgent)
47     : InspectorConsoleAgent(context, heapAgent)
48 {
49 }
50
51 void WebConsoleAgent::getLoggingChannels(ErrorString&, RefPtr<JSON::ArrayOf<Inspector::Protocol::Console::Channel>>& channels)
52 {
53     static const struct ChannelTable {
54         NeverDestroyed<String> name;
55         Inspector::Protocol::Console::ChannelSource source;
56     } channelTable[] = {
57         { MAKE_STATIC_STRING_IMPL("WebRTC"), Inspector::Protocol::Console::ChannelSource::WebRTC },
58         { MAKE_STATIC_STRING_IMPL("Media"), Inspector::Protocol::Console::ChannelSource::Media },
59         { MAKE_STATIC_STRING_IMPL("MediaSource"), Inspector::Protocol::Console::ChannelSource::MediaSource },
60     };
61
62     channels = JSON::ArrayOf<Inspector::Protocol::Console::Channel>::create();
63
64     size_t length = WTF_ARRAY_LENGTH(channelTable);
65     for (size_t i = 0; i < length; ++i) {
66         auto* logChannel = getLogChannel(channelTable[i].name);
67         if (!logChannel)
68             return;
69
70         auto level = Inspector::Protocol::Console::ChannelLevel::Off;
71         if (logChannel->state != WTFLogChannelState::Off) {
72             switch (logChannel->level) {
73             case WTFLogLevel::Always:
74             case WTFLogLevel::Error:
75             case WTFLogLevel::Warning:
76             case WTFLogLevel::Info:
77                 level = Inspector::Protocol::Console::ChannelLevel::Basic;
78                 break;
79             case WTFLogLevel::Debug:
80                 level = Inspector::Protocol::Console::ChannelLevel::Verbose;
81                 break;
82             }
83         }
84
85         auto channel = Inspector::Protocol::Console::Channel::create()
86             .setSource(channelTable[i].source)
87             .setLevel(level)
88             .release();
89         channels->addItem(WTFMove(channel));
90     }
91 }
92
93 static Optional<std::pair<WTFLogChannelState, WTFLogLevel>> channelConfigurationForString(const String& levelString)
94 {
95     WTFLogChannelState state;
96     WTFLogLevel level;
97
98     if (equalIgnoringASCIICase(levelString, "off")) {
99         state = WTFLogChannelState::Off;
100         level = WTFLogLevel::Error;
101     } else {
102         state = WTFLogChannelState::On;
103         if (equalIgnoringASCIICase(levelString, "basic"))
104             level = WTFLogLevel::Warning;
105         else if (equalIgnoringASCIICase(levelString, "verbose"))
106             level = WTFLogLevel::Debug;
107         else
108             return WTF::nullopt;
109     }
110
111     return { { state, level } };
112 }
113
114 void WebConsoleAgent::setLoggingChannelLevel(ErrorString& errorString, const String& channelName, const String& channelLevel)
115 {
116     auto* channel = getLogChannel(channelName.utf8().data());
117     if (!channel) {
118         errorString = "Logging channel not found"_s;
119         return;
120     }
121
122     auto configuration = channelConfigurationForString(channelLevel);
123     if (!configuration) {
124         errorString = "Invalid logging level"_s;
125         return;
126     }
127
128     channel->state = configuration.value().first;
129     channel->level = configuration.value().second;
130 }
131
132 void WebConsoleAgent::frameWindowDiscarded(DOMWindow* window)
133 {
134     for (auto& message : m_consoleMessages) {
135         JSC::ExecState* exec = message->scriptState();
136         if (!exec)
137             continue;
138         if (domWindowFromExecState(exec) != window)
139             continue;
140         message->clear();
141     }
142
143     static_cast<WebInjectedScriptManager&>(m_injectedScriptManager).discardInjectedScriptsFor(window);
144 }
145
146 void WebConsoleAgent::didReceiveResponse(unsigned long requestIdentifier, const ResourceResponse& response)
147 {
148     if (!m_injectedScriptManager.inspectorEnvironment().developerExtrasEnabled())
149         return;
150
151     if (response.httpStatusCode() >= 400) {
152         String message = makeString("Failed to load resource: the server responded with a status of ", response.httpStatusCode(), " (", response.httpStatusText(), ')');
153         addMessageToConsole(std::make_unique<ConsoleMessage>(MessageSource::Network, MessageType::Log, MessageLevel::Error, message, response.url().string(), 0, 0, nullptr, requestIdentifier));
154     }
155 }
156
157 void WebConsoleAgent::didFailLoading(unsigned long requestIdentifier, const ResourceError& error)
158 {
159     if (!m_injectedScriptManager.inspectorEnvironment().developerExtrasEnabled())
160         return;
161
162     // Report failures only.
163     if (error.isCancellation())
164         return;
165
166     StringBuilder message;
167     message.appendLiteral("Failed to load resource");
168     if (!error.localizedDescription().isEmpty()) {
169         message.appendLiteral(": ");
170         message.append(error.localizedDescription());
171     }
172
173     addMessageToConsole(std::make_unique<ConsoleMessage>(MessageSource::Network, MessageType::Log, MessageLevel::Error, message.toString(), error.failingURL(), 0, 0, nullptr, requestIdentifier));
174 }
175
176 } // namespace WebCore