[PDF Ink Signatures] Add metric for PDFs loaded with V2 Ink annotations
Add a metric to track the number of PDFs loaded with V2 Ink annotations. In order to do so, add a method in PDFiumEngine to check if a PDF has any V2 Ink paths, without having to store and transform the paths. This metric only tracks PDFs loaded for users with Ink2 enabled. Bug: 380433757 Change-Id: I412ab1cb4a9b9a763e0f704527e234145b12e306 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6181044 Reviewed-by: Alan Screen <awscreen@chromium.org> Commit-Queue: Andy Phan <andyphan@chromium.org> Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com> Reviewed-by: Lei Zhang <thestig@chromium.org> Cr-Commit-Position: refs/heads/main@{#1411985}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
17cbd339ff
commit
54565c8a1d
@ -158,4 +158,8 @@ void ReportEraseStroke(float size, ink::StrokeInput::ToolType tool_type) {
|
||||
ReportStrokeInputDeviceType(tool_type);
|
||||
}
|
||||
|
||||
void RecordPdfLoadedWithV2InkAnnotations(bool has_annotations) {
|
||||
base::UmaHistogramBoolean("PDF.LoadedWithV2InkAnnotations", has_annotations);
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
@ -105,6 +105,8 @@ void ReportDrawStroke(PdfInkBrush::Type type,
|
||||
|
||||
void ReportEraseStroke(float size, ink::StrokeInput::ToolType tool_type);
|
||||
|
||||
void RecordPdfLoadedWithV2InkAnnotations(bool has_annotations);
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_PDF_INK_METRICS_HANDLER_H_
|
||||
|
@ -124,6 +124,7 @@
|
||||
#if BUILDFLAG(ENABLE_PDF_INK2)
|
||||
#include "base/memory/raw_ref.h"
|
||||
#include "pdf/pdf_ink_ids.h"
|
||||
#include "pdf/pdf_ink_metrics_handler.h"
|
||||
#include "pdf/pdf_ink_module.h"
|
||||
#include "pdf/pdf_ink_module_client.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
@ -2472,6 +2473,14 @@ void PdfViewWebPlugin::RecordDocumentMetrics() {
|
||||
return;
|
||||
|
||||
metrics_handler_->RecordDocumentMetrics(engine_->GetDocumentMetadata());
|
||||
|
||||
#if BUILDFLAG(ENABLE_PDF_INK2)
|
||||
// `metrics_handler_` is only initialized when not in Print Preview, so the
|
||||
// V2 ink annotations load metric will not count Print Preview loads.
|
||||
if (ink_module_) {
|
||||
RecordPdfLoadedWithV2InkAnnotations(engine_->ContainsV2InkPath());
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_PDF_INK2)
|
||||
}
|
||||
|
||||
void PdfViewWebPlugin::SendAttachments() {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "base/test/metrics/histogram_tester.h"
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
#include "base/test/values_test_util.h"
|
||||
#include "base/time/time.h"
|
||||
@ -115,6 +116,11 @@ using ::testing::Return;
|
||||
using ::testing::SaveArg;
|
||||
using ::testing::SizeIs;
|
||||
|
||||
#if BUILDFLAG(ENABLE_PDF_INK2)
|
||||
constexpr char kPdfLoadedWithV2InkAnnotationsMetric[] =
|
||||
"PDF.LoadedWithV2InkAnnotations";
|
||||
#endif // BUILDFLAG(ENABLE_PDF_INK2)
|
||||
|
||||
// `kCanvasSize` needs to be big enough to hold plugin's snapshots during
|
||||
// testing.
|
||||
constexpr gfx::Size kCanvasSize(100, 100);
|
||||
@ -3040,6 +3046,51 @@ TEST_F(PdfViewWebPluginInk2SaveTest, AnnotationInEditMode) {
|
||||
|
||||
pdf_receiver_.FlushForTesting();
|
||||
}
|
||||
|
||||
using PdfViewWebPluginInkMetricTest = PdfViewWebPluginInkTest;
|
||||
|
||||
TEST_F(PdfViewWebPluginInkMetricTest, LoadedWithoutV2InkAnnotations) {
|
||||
base::HistogramTester histograms;
|
||||
|
||||
EXPECT_CALL(*engine_ptr_, ContainsV2InkPath()).WillOnce(Return(false));
|
||||
plugin_->DocumentLoadComplete();
|
||||
|
||||
histograms.ExpectUniqueSample(kPdfLoadedWithV2InkAnnotationsMetric, false, 1);
|
||||
}
|
||||
|
||||
TEST_F(PdfViewWebPluginInkMetricTest, LoadedWithV2InkAnnotations) {
|
||||
base::HistogramTester histograms;
|
||||
|
||||
EXPECT_CALL(*engine_ptr_, ContainsV2InkPath()).WillOnce(Return(true));
|
||||
plugin_->DocumentLoadComplete();
|
||||
|
||||
histograms.ExpectUniqueSample(kPdfLoadedWithV2InkAnnotationsMetric, true, 1);
|
||||
}
|
||||
|
||||
class PdfViewWebPluginPrintPreviewInkMetricTest
|
||||
: public PdfViewWebPluginPrintPreviewTest {
|
||||
private:
|
||||
base::test::ScopedFeatureList feature_list_{features::kPdfInk2};
|
||||
};
|
||||
|
||||
TEST_F(PdfViewWebPluginPrintPreviewInkMetricTest,
|
||||
LoadedWithV2InkAnnotationsDoesNotCountPrintPreview) {
|
||||
base::HistogramTester histograms;
|
||||
|
||||
OnMessageWithEngineUpdate(ParseMessage(R"({
|
||||
"type": "resetPrintPreviewMode",
|
||||
"url": "chrome-untrusted://print/0/0/print.pdf",
|
||||
"grayscale": false,
|
||||
"pageCount": 1,
|
||||
})"));
|
||||
|
||||
EXPECT_CALL(*engine_ptr_, ContainsV2InkPath()).Times(0);
|
||||
plugin_->DocumentLoadComplete();
|
||||
|
||||
// The V2 ink annotations PDF load metric should not increment for Print
|
||||
// Preview.
|
||||
histograms.ExpectTotalCount(kPdfLoadedWithV2InkAnnotationsMetric, 0);
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_PDF_INK2)
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
@ -4459,6 +4459,15 @@ void PDFiumEngine::DiscardStroke(int page_index, InkStrokeId id) {
|
||||
ink_stroke_objects_map_.erase(it);
|
||||
}
|
||||
|
||||
bool PDFiumEngine::ContainsV2InkPath() const {
|
||||
for (const auto& page : pages_) {
|
||||
if (PageContainsV2InkPath(page->GetPage())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<InkModeledShapeId, ink::PartitionedMesh>
|
||||
PDFiumEngine::LoadV2InkPathsForPage(int page_index) {
|
||||
CHECK(PageIndexInBounds(page_index));
|
||||
|
@ -396,6 +396,10 @@ class PDFiumEngine : public DocumentLoader::Client, public IFSDK_PAUSE {
|
||||
// `ApplyStroke()`. Virtual to support testing.
|
||||
virtual void DiscardStroke(int page_index, InkStrokeId id);
|
||||
|
||||
// Returns whether any of the pages contains a "V2" path created by Ink.
|
||||
// Virtual to support testing.
|
||||
virtual bool ContainsV2InkPath() const;
|
||||
|
||||
// Loads "V2" Ink paths from a page in the PDF identified by `page_index`. The
|
||||
// `page_index` must be in bounds.
|
||||
//
|
||||
|
@ -2046,6 +2046,20 @@ TEST_P(PDFiumEngineInkTest, CannotSelectTextInAnnotationMode) {
|
||||
EXPECT_THAT(engine->GetSelectedText(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST_P(PDFiumEngineInkTest, ContainsV2InkPath) {
|
||||
NiceMock<MockTestClient> client;
|
||||
std::unique_ptr<PDFiumEngine> engine =
|
||||
InitializeEngine(&client, FILE_PATH_LITERAL("blank.pdf"));
|
||||
ASSERT_TRUE(engine);
|
||||
ASSERT_EQ(1, engine->GetNumberOfPages());
|
||||
EXPECT_FALSE(engine->ContainsV2InkPath());
|
||||
|
||||
engine = InitializeEngine(&client, FILE_PATH_LITERAL("ink_v2.pdf"));
|
||||
ASSERT_TRUE(engine);
|
||||
ASSERT_EQ(1, engine->GetNumberOfPages());
|
||||
EXPECT_TRUE(engine->ContainsV2InkPath());
|
||||
}
|
||||
|
||||
TEST_P(PDFiumEngineInkTest, LoadV2InkPathsForPage) {
|
||||
NiceMock<MockTestClient> client;
|
||||
std::unique_ptr<PDFiumEngine> engine =
|
||||
|
@ -150,6 +150,20 @@ std::optional<ink::PartitionedMesh> ReadV2InkModeledShapeFromPath(
|
||||
|
||||
} // namespace
|
||||
|
||||
bool PageContainsV2InkPath(FPDF_PAGE page) {
|
||||
if (!page) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int page_object_count = FPDFPage_CountObjects(page);
|
||||
for (int i = 0; i < page_object_count; ++i) {
|
||||
if (IsV2InkPath(FPDFPage_GetObject(page, i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<ReadV2InkPathResult> ReadV2InkPathsFromPageAsModeledShapes(
|
||||
FPDF_PAGE page) {
|
||||
std::vector<ReadV2InkPathResult> results;
|
||||
|
@ -24,6 +24,10 @@ struct ReadV2InkPathResult {
|
||||
ink::PartitionedMesh shape;
|
||||
};
|
||||
|
||||
// Returns whether the given `page` contains a "V2" path created by Ink.
|
||||
// Returns false if `page` is null.
|
||||
bool PageContainsV2InkPath(FPDF_PAGE page);
|
||||
|
||||
// For the given `page`, iterate through all page objects and import "V2" paths
|
||||
// created by Ink as ink::PartitionedMeshs. For each shape, also return its
|
||||
// associated page object. The shapes do not have outlines and are only suitable
|
||||
|
@ -109,6 +109,8 @@ class TestPDFiumEngine : public PDFiumEngine {
|
||||
|
||||
MOCK_METHOD(void, DiscardStroke, (int, InkStrokeId), (override));
|
||||
|
||||
MOCK_METHOD(bool, ContainsV2InkPath, (), (const override));
|
||||
|
||||
MOCK_METHOD((std::map<InkModeledShapeId, ink::PartitionedMesh>),
|
||||
LoadV2InkPathsForPage,
|
||||
(int),
|
||||
|
@ -146,6 +146,16 @@ chromium-metrics-reviews@google.com.
|
||||
</token>
|
||||
</histogram>
|
||||
|
||||
<histogram name="PDF.LoadedWithV2InkAnnotations" enum="Boolean"
|
||||
expires_after="2025-12-01">
|
||||
<owner>andyphan@chromium.org</owner>
|
||||
<owner>thestig@chromium.org</owner>
|
||||
<summary>
|
||||
Tracks the number of PDF documents loaded with existing V2 ink annotations
|
||||
in the PDF viewer.
|
||||
</summary>
|
||||
</histogram>
|
||||
|
||||
<histogram name="PDF.LoadStatus2" enum="ChromePDFViewerLoadStatus"
|
||||
expires_after="2025-06-08">
|
||||
<owner>kmoon@chromium.org</owner>
|
||||
|
Reference in New Issue
Block a user