blob: a8ff441153f1134c509a7bc076e8c63ec5d976fa [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/loader/previews_resource_loading_hints.h"
#include "base/metrics/histogram_macros.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/renderer/core/dom/document.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_types.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
namespace {
String GetConsoleLogStringForBlockedLoad(const KURL& url) {
return "[Intervention] Non-critical resource " + url.GetString() +
" is blocked due to page load being slow. Learn more at "
"https://www.chromestatus.com/feature/4510564810227712.";
}
} // namespace
// static
PreviewsResourceLoadingHints* PreviewsResourceLoadingHints::Create(
ExecutionContext& execution_context,
int64_t ukm_source_id,
const std::vector<WTF::String>& subresource_patterns_to_block) {
return MakeGarbageCollected<PreviewsResourceLoadingHints>(
&execution_context, ukm_source_id, subresource_patterns_to_block);
}
PreviewsResourceLoadingHints::PreviewsResourceLoadingHints(
ExecutionContext* execution_context,
int64_t ukm_source_id,
const std::vector<WTF::String>& subresource_patterns_to_block)
: execution_context_(execution_context),
ukm_source_id_(ukm_source_id),
subresource_patterns_to_block_(subresource_patterns_to_block) {
DCHECK_NE(ukm::kInvalidSourceId, ukm_source_id_);
subresource_patterns_to_block_usage_.assign(
subresource_patterns_to_block.size(), false);
blocked_resource_load_priority_counts_.fill(0);
}
PreviewsResourceLoadingHints::~PreviewsResourceLoadingHints() = default;
bool PreviewsResourceLoadingHints::AllowLoad(
const KURL& resource_url,
ResourceLoadPriority resource_load_priority) const {
if (!resource_url.ProtocolIsInHTTPFamily())
return true;
WTF::String resource_url_string = resource_url.GetString();
resource_url_string = resource_url_string.Left(resource_url.PathEnd());
bool allow_load = true;
int pattern_index = 0;
for (const WTF::String& subresource_pattern :
subresource_patterns_to_block_) {
// TODO(tbansal): https://crbug.com/856247. Add support for wildcard
// matching.
if (resource_url_string.Find(subresource_pattern) != kNotFound) {
allow_load = false;
subresource_patterns_to_block_usage_[pattern_index] = true;
blocked_resource_load_priority_counts_[static_cast<int>(
resource_load_priority)]++;
break;
}
pattern_index++;
}
UMA_HISTOGRAM_BOOLEAN("ResourceLoadingHints.ResourceLoadingBlocked",
!allow_load);
if (!allow_load) {
ReportBlockedLoading(resource_url);
UMA_HISTOGRAM_ENUMERATION(
"ResourceLoadingHints.ResourceLoadingBlocked.ResourceLoadPriority."
"Blocked",
resource_load_priority,
static_cast<int>(ResourceLoadPriority::kHighest) + 1);
} else {
UMA_HISTOGRAM_ENUMERATION(
"ResourceLoadingHints.ResourceLoadingBlocked.ResourceLoadPriority."
"Allowed",
resource_load_priority,
static_cast<int>(ResourceLoadPriority::kHighest) + 1);
}
return allow_load;
}
void PreviewsResourceLoadingHints::ReportBlockedLoading(
const KURL& resource_url) const {
execution_context_->AddConsoleMessage(
ConsoleMessage::Create(kOtherMessageSource, kWarningMessageLevel,
GetConsoleLogStringForBlockedLoad(resource_url)));
}
void PreviewsResourceLoadingHints::Trace(blink::Visitor* visitor) {
visitor->Trace(execution_context_);
}
void PreviewsResourceLoadingHints::RecordUKM(
ukm::UkmRecorder* ukm_recorder) const {
DCHECK(ukm_recorder);
size_t patterns_to_block_used_count = 0;
for (bool pattern_used : subresource_patterns_to_block_usage_) {
if (pattern_used) {
patterns_to_block_used_count++;
}
}
ukm::builders::PreviewsResourceLoadingHints(ukm_source_id_)
.Setpatterns_to_block_total(subresource_patterns_to_block_.size())
.Setpatterns_to_block_used(patterns_to_block_used_count)
.Setblocked_very_low_priority(
blocked_resource_load_priority_counts_[static_cast<int>(
ResourceLoadPriority::kVeryLow)])
.Setblocked_low_priority(
blocked_resource_load_priority_counts_[static_cast<int>(
ResourceLoadPriority::kLow)])
.Setblocked_medium_priority(
blocked_resource_load_priority_counts_[static_cast<int>(
ResourceLoadPriority::kMedium)])
.Setblocked_high_priority(
blocked_resource_load_priority_counts_[static_cast<int>(
ResourceLoadPriority::kHigh)])
.Setblocked_very_high_priority(
blocked_resource_load_priority_counts_[static_cast<int>(
ResourceLoadPriority::kVeryHigh)])
.Record(ukm_recorder);
}
} // namespace blink