blob: bfe16e6ce7f077e88481e557b7006327009998f2 [file] [log] [blame]
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "third_party/blink/renderer/core/frame/frame_console.h"
#include <memory>
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/inspector/console_message_storage.h"
#include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
FrameConsole::FrameConsole(LocalFrame& frame) : frame_(&frame) {}
void FrameConsole::AddMessage(ConsoleMessage* console_message) {
// PlzNavigate: when trying to commit a navigation, the SourceLocation
// information for how the request was triggered has been stored in the
// provisional DocumentLoader. Use it instead.
DocumentLoader* provisional_loader =
frame_->Loader().GetProvisionalDocumentLoader();
if (provisional_loader) {
std::unique_ptr<SourceLocation> source_location =
provisional_loader->CopySourceLocation();
if (source_location) {
Vector<DOMNodeId> nodes(console_message->Nodes());
LocalFrame* frame = console_message->Frame();
console_message = ConsoleMessage::Create(
console_message->Source(), console_message->Level(),
console_message->Message(), std::move(source_location));
console_message->SetNodes(frame, std::move(nodes));
}
}
if (AddMessageToStorage(console_message))
ReportMessageToClient(console_message->Source(), console_message->Level(),
console_message->Message(),
console_message->Location());
}
bool FrameConsole::AddMessageToStorage(ConsoleMessage* console_message) {
if (!frame_->GetDocument() || !frame_->GetPage())
return false;
frame_->GetPage()->GetConsoleMessageStorage().AddConsoleMessage(
frame_->GetDocument(), console_message);
return true;
}
void FrameConsole::ReportMessageToClient(MessageSource source,
MessageLevel level,
const String& message,
SourceLocation* location) {
if (source == kNetworkMessageSource)
return;
String url = location->Url();
String stack_trace;
if (source == kConsoleAPIMessageSource) {
if (!frame_->GetPage())
return;
if (frame_->GetChromeClient().ShouldReportDetailedMessageForSource(*frame_,
url)) {
std::unique_ptr<SourceLocation> full_location =
SourceLocation::CaptureWithFullStackTrace();
if (!full_location->IsUnknown())
stack_trace = full_location->ToString();
}
} else {
if (!location->IsUnknown() &&
frame_->GetChromeClient().ShouldReportDetailedMessageForSource(*frame_,
url))
stack_trace = location->ToString();
}
frame_->GetChromeClient().AddMessageToConsole(
frame_, source, level, message, location->LineNumber(), url, stack_trace);
}
void FrameConsole::ReportResourceResponseReceived(
DocumentLoader* loader,
unsigned long request_identifier,
const ResourceResponse& response) {
if (!loader)
return;
if (response.HttpStatusCode() < 400)
return;
if (response.WasFallbackRequiredByServiceWorker())
return;
String message =
"Failed to load resource: the server responded with a status of " +
String::Number(response.HttpStatusCode()) + " (" +
response.HttpStatusText() + ')';
ConsoleMessage* console_message = ConsoleMessage::CreateForRequest(
kNetworkMessageSource, kErrorMessageLevel, message,
response.CurrentRequestUrl().GetString(), loader, request_identifier);
AddMessage(console_message);
}
void FrameConsole::DidFailLoading(DocumentLoader* loader,
unsigned long request_identifier,
const ResourceError& error) {
if (error.IsCancellation()) // Report failures only.
return;
StringBuilder message;
message.Append("Failed to load resource");
if (!error.LocalizedDescription().IsEmpty()) {
message.Append(": ");
message.Append(error.LocalizedDescription());
}
AddMessageToStorage(ConsoleMessage::CreateForRequest(
kNetworkMessageSource, kErrorMessageLevel, message.ToString(),
error.FailingURL(), loader, request_identifier));
}
void FrameConsole::Trace(blink::Visitor* visitor) {
visitor->Trace(frame_);
ConsoleLoggerImplBase::Trace(visitor);
}
} // namespace blink