[go: nahoru, domu]

blob: 84974ec84cd2ec37e0f2fb724a6d350d9b5b274f [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// 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/lazy_image_helper.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/frame_owner.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/html/lazy_load_image_observer.h"
#include "third_party/blink/renderer/core/html/loading_attribute.h"
namespace blink {
namespace {
// Records |bytes| to |histogram_name| in kilobytes (i.e., bytes / 1024).
// https://almanac.httparchive.org/en/2022/page-weight#fig-12 reports the 90th
// percentile of jpeg images is 213KB with a max of ~64MB. The max bucket size
// has been set at 64MB to capture this range with as much granularity as
// possible.
#define IMAGE_BYTES_HISTOGRAM(histogram_name, bytes) \
UMA_HISTOGRAM_CUSTOM_COUNTS(histogram_name, \
base::saturated_cast<int>((bytes) / 1024), 1, \
64 * 1024, 50)
Document* GetRootDocumentOrNull(Node* node) {
if (LocalFrame* frame = node->GetDocument().GetFrame()) {
return frame->LocalFrameRoot().GetDocument();
}
return nullptr;
}
} // namespace
// static
void LazyImageHelper::StartMonitoring(Element* element) {
if (Document* document = GetRootDocumentOrNull(element)) {
document->EnsureLazyLoadImageObserver().StartMonitoringNearViewport(
document, element);
}
}
void LazyImageHelper::StopMonitoring(Element* element) {
if (Document* document = GetRootDocumentOrNull(element)) {
document->EnsureLazyLoadImageObserver().StopMonitoring(element);
}
}
// static
bool LazyImageHelper::LoadAllImagesAndBlockLoadEvent(Document& document) {
if (Document* root_document = GetRootDocumentOrNull(&document)) {
return root_document->EnsureLazyLoadImageObserver()
.LoadAllImagesAndBlockLoadEvent(document);
}
return false;
}
// static
bool LazyImageHelper::ShouldDeferImageLoad(LocalFrame& frame,
HTMLImageElement* html_image) {
// Do not lazyload image elements when JavaScript is disabled, regardless of
// the `loading` attribute.
if (!frame.DomWindow()->CanExecuteScripts(kNotAboutToExecuteScript)) {
return false;
}
LoadingAttributeValue loading_attr = GetLoadingAttributeValue(
html_image->FastGetAttribute(html_names::kLoadingAttr));
if (loading_attr == LoadingAttributeValue::kEager) {
UseCounter::Count(frame.GetDocument(),
WebFeature::kLazyLoadImageLoadingAttributeEager);
return false;
}
if (loading_attr != LoadingAttributeValue::kLazy) {
return false;
}
UseCounter::Count(frame.GetDocument(),
WebFeature::kLazyLoadImageLoadingAttributeLazy);
if (frame.GetLazyLoadImageSetting() ==
LocalFrame::LazyLoadImageSetting::kDisabled) {
return false;
}
return true;
}
// static
void LazyImageHelper::StartMonitoringVisibilityMetrics(
HTMLImageElement* html_image) {
if (Document* root_document = GetRootDocumentOrNull(html_image)) {
root_document->EnsureLazyLoadImageObserver().StartMonitoringVisibility(
root_document, html_image);
}
}
void LazyImageHelper::RecordMetricsOnLoadFinished(
HTMLImageElement* image_element) {
// TODO(pdr): We should only report metrics for images that were actually lazy
// loaded, and checking the attribute alone is not sufficient. See:
// `LazyImageHelper::ShouldDeferImageLoad`.
if (!image_element->HasLazyLoadingAttribute()) {
return;
}
Document* root_document = GetRootDocumentOrNull(image_element);
if (!root_document) {
return;
}
if (ImageResourceContent* content = image_element->CachedImage()) {
int64_t response_size = content->GetResponse().EncodedDataLength();
IMAGE_BYTES_HISTOGRAM("Blink.LazyLoadedImage.Size", response_size);
if (!root_document->LoadEventFinished()) {
IMAGE_BYTES_HISTOGRAM("Blink.LazyLoadedImageBeforeDocumentOnLoad.Size",
response_size);
}
}
root_document->EnsureLazyLoadImageObserver().OnLoadFinished(image_element);
}
} // namespace blink