0

[lensoverlay] Record metric for page count

Adds a metric for the PDF page count retrieved from the renderer.

Bug: 366028802
Change-Id: I90dfaccac0ce507784bd3e8ce61f70119abd65f4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6032193
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Duncan Mercer <mercerd@google.com>
Reviewed-by: Justin Donnelly <jdonnelly@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1385207}
This commit is contained in:
Duncan Mercer
2024-11-19 21:12:16 +00:00
committed by Chromium LUCI CQ
parent bc60948a72
commit 10432e5451
9 changed files with 86 additions and 31 deletions

@@ -55,6 +55,7 @@
#include "components/find_in_page/find_tab_helper.h" #include "components/find_in_page/find_tab_helper.h"
#include "components/lens/lens_features.h" #include "components/lens/lens_features.h"
#include "components/lens/lens_overlay_metrics.h" #include "components/lens/lens_overlay_metrics.h"
#include "components/lens/lens_overlay_page_content_mime_type.h"
#include "components/lens/lens_overlay_permission_utils.h" #include "components/lens/lens_overlay_permission_utils.h"
#include "components/permissions/permission_request_manager.h" #include "components/permissions/permission_request_manager.h"
#include "components/sessions/content/session_tab_helper.h" #include "components/sessions/content/session_tab_helper.h"
@@ -1487,12 +1488,13 @@ void LensOverlayController::ContinueCreateInitializationData(
void LensOverlayController::StorePageContentAndContinueInitialization( void LensOverlayController::StorePageContentAndContinueInitialization(
std::unique_ptr<OverlayInitializationData> initialization_data, std::unique_ptr<OverlayInitializationData> initialization_data,
std::vector<uint8_t> bytes, std::vector<uint8_t> bytes,
lens::PageContentMimeType content_type) { lens::PageContentMimeType content_type,
std::optional<uint32_t> page_count) {
initialization_data->page_content_bytes_ = bytes; initialization_data->page_content_bytes_ = bytes;
initialization_data->page_content_type_ = content_type; initialization_data->page_content_type_ = content_type;
InitializeOverlay(std::move(initialization_data)); InitializeOverlay(std::move(initialization_data));
RecordDocumentSizes(); RecordDocumentMetrics(page_count);
} }
void LensOverlayController::GetPageContextualization( void LensOverlayController::GetPageContextualization(
@@ -1500,7 +1502,7 @@ void LensOverlayController::GetPageContextualization(
// If the contextual searchbox is disabled, exit early. // If the contextual searchbox is disabled, exit early.
if (!lens::features::IsLensOverlayContextualSearchboxEnabled()) { if (!lens::features::IsLensOverlayContextualSearchboxEnabled()) {
std::move(callback).Run(std::vector<uint8_t>(), std::move(callback).Run(std::vector<uint8_t>(),
lens::PageContentMimeType::kNone); lens::PageContentMimeType::kNone, std::nullopt);
return; return;
} }
@@ -1540,21 +1542,22 @@ void LensOverlayController::GetPageContextualization(
} }
std::move(callback).Run(std::vector<uint8_t>(), std::move(callback).Run(std::vector<uint8_t>(),
lens::PageContentMimeType::kNone); lens::PageContentMimeType::kNone, std::nullopt);
} }
#if BUILDFLAG(ENABLE_PDF) #if BUILDFLAG(ENABLE_PDF)
void LensOverlayController::OnPdfBytesReceived( void LensOverlayController::OnPdfBytesReceived(
PageContentRetrievedCallback callback, PageContentRetrievedCallback callback,
pdf::mojom::PdfListener::GetPdfBytesStatus status, pdf::mojom::PdfListener::GetPdfBytesStatus status,
const std::vector<uint8_t>& bytes) { const std::vector<uint8_t>& bytes,
uint32_t page_count) {
// TODO(b/370530197): Show user error message if status is not success. // TODO(b/370530197): Show user error message if status is not success.
if (status != pdf::mojom::PdfListener::GetPdfBytesStatus::kSuccess) { if (status != pdf::mojom::PdfListener::GetPdfBytesStatus::kSuccess) {
std::move(callback).Run(std::vector<uint8_t>(), std::move(callback).Run(std::vector<uint8_t>(),
lens::PageContentMimeType::kPdf); lens::PageContentMimeType::kPdf, page_count);
return; return;
} }
std::move(callback).Run(bytes, lens::PageContentMimeType::kPdf); std::move(callback).Run(bytes, lens::PageContentMimeType::kPdf, page_count);
} }
#endif // BUILDFLAG(ENABLE_PDF) #endif // BUILDFLAG(ENABLE_PDF)
@@ -1564,12 +1567,13 @@ void LensOverlayController::OnInnerTextReceived(
if (!result || result->inner_text.size() > if (!result || result->inner_text.size() >
lens::features::GetLensOverlayFileUploadLimitBytes()) { lens::features::GetLensOverlayFileUploadLimitBytes()) {
std::move(callback).Run(std::vector<uint8_t>(), std::move(callback).Run(std::vector<uint8_t>(),
lens::PageContentMimeType::kPlainText); lens::PageContentMimeType::kPlainText,
std::nullopt);
return; return;
} }
std::move(callback).Run(std::vector<uint8_t>(result->inner_text.begin(), std::move(callback).Run(std::vector<uint8_t>(result->inner_text.begin(),
result->inner_text.end()), result->inner_text.end()),
lens::PageContentMimeType::kPlainText); lens::PageContentMimeType::kPlainText, std::nullopt);
} }
void LensOverlayController::OnInnerHtmlReceived( void LensOverlayController::OnInnerHtmlReceived(
@@ -1578,11 +1582,11 @@ void LensOverlayController::OnInnerHtmlReceived(
if (!result.has_value() || if (!result.has_value() ||
result->size() > lens::features::GetLensOverlayFileUploadLimitBytes()) { result->size() > lens::features::GetLensOverlayFileUploadLimitBytes()) {
std::move(callback).Run(std::vector<uint8_t>(), std::move(callback).Run(std::vector<uint8_t>(),
lens::PageContentMimeType::kHtml); lens::PageContentMimeType::kHtml, std::nullopt);
return; return;
} }
std::move(callback).Run(std::vector<uint8_t>(result->begin(), result->end()), std::move(callback).Run(std::vector<uint8_t>(result->begin(), result->end()),
lens::PageContentMimeType::kHtml); lens::PageContentMimeType::kHtml, std::nullopt);
} }
void LensOverlayController::AddBoundingBoxesToInitializationData( void LensOverlayController::AddBoundingBoxesToInitializationData(
@@ -1636,7 +1640,8 @@ void LensOverlayController::TryUpdatePageContextualization() {
void LensOverlayController::UpdatePageContextualization( void LensOverlayController::UpdatePageContextualization(
std::vector<uint8_t> bytes, std::vector<uint8_t> bytes,
lens::PageContentMimeType content_type) { lens::PageContentMimeType content_type,
std::optional<uint32_t> page_count) {
if (!lens::features::IsLensOverlayContextualSearchboxEnabled()) { if (!lens::features::IsLensOverlayContextualSearchboxEnabled()) {
return; return;
} }
@@ -1664,7 +1669,7 @@ void LensOverlayController::UpdatePageContextualization(
initialization_data_->page_content_bytes_, initialization_data_->page_content_bytes_,
initialization_data_->page_content_type_, GetPageURL()); initialization_data_->page_content_type_, GetPageURL());
RecordDocumentSizes(); RecordDocumentMetrics(page_count);
} }
void LensOverlayController::UpdateGhostLoaderState(bool suppress_ghost_loader, void LensOverlayController::UpdateGhostLoaderState(bool suppress_ghost_loader,
@@ -2714,11 +2719,18 @@ void LensOverlayController::RecordEndOfSessionMetrics(
session_duration); session_duration);
} }
void LensOverlayController::RecordDocumentSizes() { void LensOverlayController::RecordDocumentMetrics(
std::optional<uint32_t> page_count) {
auto content_type = initialization_data_->page_content_type_; auto content_type = initialization_data_->page_content_type_;
lens::RecordDocumentSizeBytes( lens::RecordDocumentSizeBytes(
content_type, initialization_data_->page_content_bytes_.size()); content_type, initialization_data_->page_content_bytes_.size());
if (page_count.has_value() &&
content_type == lens::PageContentMimeType::kPdf) {
lens::RecordPdfPageCount(page_count.value());
return;
}
// Fetch and record the other content type for representing the webpage. // Fetch and record the other content type for representing the webpage.
auto* render_frame_host = tab_->GetContents()->GetPrimaryMainFrame(); auto* render_frame_host = tab_->GetContents()->GetPrimaryMainFrame();
if (content_type == lens::PageContentMimeType::kHtml) { if (content_type == lens::PageContentMimeType::kHtml) {

@@ -96,10 +96,15 @@ class Profile;
extern void* kLensOverlayPreselectionWidgetIdentifier; extern void* kLensOverlayPreselectionWidgetIdentifier;
// Callback type alias for page content bytes retrieved. // Callback type alias for page content bytes retrieved. `content_type` is the
// mime type of the bytes. `pdf_page_count` is the number of pages in the
// document being retrieved, not necessarily the number of pages in `bytes`. For
// example, if the document is a PDF, `pdf_page_count` is the number of pages in
// the PDF, while `bytes` could be empty because the PDF is too large.
using PageContentRetrievedCallback = using PageContentRetrievedCallback =
base::OnceCallback<void(std::vector<uint8_t> bytes, base::OnceCallback<void(std::vector<uint8_t> bytes,
lens::PageContentMimeType content_type)>; lens::PageContentMimeType content_type,
std::optional<uint32_t> pdf_page_count)>;
// Manages all state associated with the lens overlay. // Manages all state associated with the lens overlay.
// This class is not thread safe. It should only be used from the browser // This class is not thread safe. It should only be used from the browser
@@ -655,11 +660,13 @@ class LensOverlayController : public LensSearchboxClient,
const std::vector<gfx::Rect>& all_bounds, const std::vector<gfx::Rect>& all_bounds,
SkBitmap rgb_screenshot); SkBitmap rgb_screenshot);
// Stores the page content and continues the initialization process. // Stores the page content and continues the initialization process. Also
// records the page count for PDF.
void StorePageContentAndContinueInitialization( void StorePageContentAndContinueInitialization(
std::unique_ptr<OverlayInitializationData> initialization_data, std::unique_ptr<OverlayInitializationData> initialization_data,
std::vector<uint8_t> bytes, std::vector<uint8_t> bytes,
lens::PageContentMimeType content_type); lens::PageContentMimeType content_type,
std::optional<uint32_t> pdf_page_count);
// Tries to fetch the underlying page content bytes to use for // Tries to fetch the underlying page content bytes to use for
// contextualization. If page content can not be retrieved, the callback will // contextualization. If page content can not be retrieved, the callback will
@@ -671,7 +678,8 @@ class LensOverlayController : public LensSearchboxClient,
// them in initialization data. // them in initialization data.
void OnPdfBytesReceived(PageContentRetrievedCallback callback, void OnPdfBytesReceived(PageContentRetrievedCallback callback,
pdf::mojom::PdfListener::GetPdfBytesStatus status, pdf::mojom::PdfListener::GetPdfBytesStatus status,
const std::vector<uint8_t>& bytes); const std::vector<uint8_t>& bytes,
uint32_t pdf_page_count);
#endif // BUILDFLAG(ENABLE_PDF) #endif // BUILDFLAG(ENABLE_PDF)
// Callback for when the inner text is retrieved from the underlying page. // Callback for when the inner text is retrieved from the underlying page.
@@ -695,7 +703,8 @@ class LensOverlayController : public LensSearchboxClient,
// Updates the query flow with the new page content bytes. A request will only // Updates the query flow with the new page content bytes. A request will only
// be sent if the bytes are different from the previous bytes sent. // be sent if the bytes are different from the previous bytes sent.
void UpdatePageContextualization(std::vector<uint8_t> bytes, void UpdatePageContextualization(std::vector<uint8_t> bytes,
lens::PageContentMimeType content_type); lens::PageContentMimeType content_type,
std::optional<uint32_t> pdf_page_count);
// Updates state of the ghost loader. |suppress_ghost_loader| is true when // Updates state of the ghost loader. |suppress_ghost_loader| is true when
// the page bytes can't be uploaded. |reset_loading_state| is true whenever // the page bytes can't be uploaded. |reset_loading_state| is true whenever
@@ -933,10 +942,11 @@ class LensOverlayController : public LensSearchboxClient,
void RecordEndOfSessionMetrics( void RecordEndOfSessionMetrics(
lens::LensOverlayDismissalSource dismissal_source); lens::LensOverlayDismissalSource dismissal_source);
// Records the UMA for the size of the document where the contextual search // Records the UMA for the metrics relating to the document where the
// box was shown. If this is a webpage, records the size of the innerHtml and // contextual search box was shown. If this is a webpage, records the size of
// the innerText. If this is a PDF, records the byte size of the PDF. // the innerHtml and the innerText. If this is a PDF, records the byte size of
void RecordDocumentSizes(); // the PDF and the number of pages. `pdf_page_count` is only used for PDFs.
void RecordDocumentMetrics(std::optional<uint32_t> pdf_page_count);
// Callback to record the size of the innerText once it is fetched. // Callback to record the size of the innerText once it is fetched.
void RecordInnerTextSize( void RecordInnerTextSize(

@@ -4235,6 +4235,10 @@ IN_PROC_BROWSER_TEST_P(LensOverlayControllerBrowserPDFContextualizationTest,
histogram_tester.ExpectTotalCount( histogram_tester.ExpectTotalCount(
"Lens.Overlay.ByContentType.Pdf.DocumentSize", "Lens.Overlay.ByContentType.Pdf.DocumentSize",
/*expected_count=*/2); /*expected_count=*/2);
// Verify the histogram two documents of one page.
histogram_tester.ExpectBucketCount(
"Lens.Overlay.ByDocumentType.Pdf.PageCount", /*sample*/ 1,
/*expected_count=*/2);
} }
IN_PROC_BROWSER_TEST_P(LensOverlayControllerBrowserPDFContextualizationTest, IN_PROC_BROWSER_TEST_P(LensOverlayControllerBrowserPDFContextualizationTest,
@@ -4314,6 +4318,9 @@ IN_PROC_BROWSER_TEST_P(LensOverlayControllerBrowserPDFContextualizationTest,
histogram_tester.ExpectTotalCount( histogram_tester.ExpectTotalCount(
"Lens.Overlay.ByContentType.Pdf.DocumentSize", "Lens.Overlay.ByContentType.Pdf.DocumentSize",
/*expected_count=*/1); /*expected_count=*/1);
histogram_tester.ExpectUniqueSample(
"Lens.Overlay.ByDocumentType.Pdf.PageCount", /*sample*/ 1,
/*expected_bucket_count=*/1);
} }
// TODO(crbug.com/378810677): Flaky on all platforms. // TODO(crbug.com/378810677): Flaky on all platforms.
@@ -4735,6 +4742,8 @@ IN_PROC_BROWSER_TEST_F(LensOverlayControllerBrowserTest,
histogram_tester.ExpectTotalCount( histogram_tester.ExpectTotalCount(
"Lens.Overlay.ByContentType.Html.DocumentSize", "Lens.Overlay.ByContentType.Html.DocumentSize",
/*expected_count=*/2); /*expected_count=*/2);
histogram_tester.ExpectTotalCount("Lens.Overlay.ByDocumentType.Pdf.PageCount",
/*expected_count=*/0);
} }
IN_PROC_BROWSER_TEST_F(LensOverlayControllerBrowserTest, IN_PROC_BROWSER_TEST_F(LensOverlayControllerBrowserTest,

@@ -304,4 +304,9 @@ void RecordDocumentSizeBytes(lens::PageContentMimeType page_content_type,
document_size_bytes / 1000); document_size_bytes / 1000);
} }
void RecordPdfPageCount(uint32_t page_count) {
base::UmaHistogramCounts1000("Lens.Overlay.ByDocumentType.Pdf.PageCount",
page_count);
}
} // namespace lens } // namespace lens

@@ -104,6 +104,10 @@ void MaybeRecordContextualSearchBoxShown(
// sliced by content type. // sliced by content type.
void RecordDocumentSizeBytes(lens::PageContentMimeType page_content_type, void RecordDocumentSizeBytes(lens::PageContentMimeType page_content_type,
size_t document_size_bytes); size_t document_size_bytes);
// Record the number of pages in a PDF.
void RecordPdfPageCount(uint32_t page_count);
} // namespace lens } // namespace lens
#endif // COMPONENTS_LENS_LENS_OVERLAY_METRICS_H_ #endif // COMPONENTS_LENS_LENS_OVERLAY_METRICS_H_

@@ -212,8 +212,8 @@ void PDFDocumentHelper::GetPdfBytes(
uint32_t size_limit, uint32_t size_limit,
pdf::mojom::PdfListener::GetPdfBytesCallback callback) { pdf::mojom::PdfListener::GetPdfBytesCallback callback) {
if (!remote_pdf_client_) { if (!remote_pdf_client_) {
std::move(callback).Run( std::move(callback).Run(pdf::mojom::PdfListener::GetPdfBytesStatus::kFailed,
pdf::mojom::PdfListener::GetPdfBytesStatus::kFailed, {}); /*bytes=*/{}, /*page_count=*/0);
return; return;
} }
remote_pdf_client_->GetPdfBytes(size_limit, std::move(callback)); remote_pdf_client_->GetPdfBytes(size_limit, std::move(callback));

@@ -28,9 +28,11 @@ interface PdfListener {
// Get PDF bytes. If the size of the PDF in bytes is larger than `size_limit`, // Get PDF bytes. If the size of the PDF in bytes is larger than `size_limit`,
// an empty vector will be returned instead. `bytes` is only guaranteed to be // an empty vector will be returned instead. `bytes` is only guaranteed to be
// from the PDF engine if `status` is `kSuccess`. // from the PDF engine if `status` is `kSuccess`. `page_count` is the number
// of pages in the PDF displayed in the renderer, not the number of pages
// returned in `bytes`.
GetPdfBytes(uint32 size_limit) GetPdfBytes(uint32 size_limit)
=> (GetPdfBytesStatus status, array<uint8> bytes); => (GetPdfBytesStatus status, array<uint8> bytes, uint32 page_count);
}; };
// Browser-side interface used by PDF renderers. // Browser-side interface used by PDF renderers.

@@ -1528,12 +1528,15 @@ void PdfViewWebPlugin::SetSelectionBounds(const gfx::PointF& base,
void PdfViewWebPlugin::GetPdfBytes(uint32_t size_limit, void PdfViewWebPlugin::GetPdfBytes(uint32_t size_limit,
GetPdfBytesCallback callback) { GetPdfBytesCallback callback) {
uint32_t page_count = engine_->GetNumberOfPages();
if (engine_->GetLoadedByteSize() > size_limit) { if (engine_->GetLoadedByteSize() > size_limit) {
std::move(callback).Run(GetPdfBytesStatus::kSizeLimitExceeded, {}); std::move(callback).Run(GetPdfBytesStatus::kSizeLimitExceeded, {},
page_count);
return; return;
} }
std::move(callback).Run(GetPdfBytesStatus::kSuccess, engine_->GetSaveData()); std::move(callback).Run(GetPdfBytesStatus::kSuccess, engine_->GetSaveData(),
page_count);
} }
bool PdfViewWebPlugin::IsValid() const { bool PdfViewWebPlugin::IsValid() const {

@@ -23,7 +23,7 @@ chromium-metrics-reviews@google.com.
<histograms> <histograms>
<!-- Represents the MIME types that are retrieved from the page content. <!-- Represents the MIME types that are retrieved from the page content.
Corresponds to the content type set in the request to the server. --> Corresponds to the content type set in the request to the server. -->
<variants name="ContentTypes"> <variants name="ContentTypes">
<variant name="Html"/> <variant name="Html"/>
@@ -124,6 +124,16 @@ chromium-metrics-reviews@google.com.
<token key="ContentType" variants="ContentTypes"/> <token key="ContentType" variants="ContentTypes"/>
</histogram> </histogram>
<histogram name="Lens.Overlay.ByDocumentType.Pdf.PageCount" units="Pages"
expires_after="2025-05-06">
<owner>mercerd@google.com</owner>
<owner>lens-chrome@google.com</owner>
<summary>
Recorded whenever a PDF is fetched from the PDF renderer. Records the number
of pages in the PDF that was fetched.
</summary>
</histogram>
<histogram name="Lens.Overlay.ByDocumentType.{DocumentType}.Invoked" <histogram name="Lens.Overlay.ByDocumentType.{DocumentType}.Invoked"
enum="Boolean" expires_after="2025-05-06"> enum="Boolean" expires_after="2025-05-06">
<owner>stanfield@google.com</owner> <owner>stanfield@google.com</owner>