blob: a138785cd3ef27541d29b66e4ed45f5c939ebf80 [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {FittingType, PdfOcrUserSelection} from './constants.js';
// Handles events specific to the PDF viewer and logs the corresponding metrics.
/**
* Records when the zoom mode is changed to fit a FittingType.
* @param fittingType the new FittingType.
*/
export function recordFitTo(fittingType: FittingType) {
if (fittingType === FittingType.FIT_TO_PAGE) {
record(UserAction.FIT_TO_PAGE);
} else if (fittingType === FittingType.FIT_TO_WIDTH) {
record(UserAction.FIT_TO_WIDTH);
}
// There is no user action to do a fit-to-height, this only happens with the
// the open param "view=FitV".
}
/** Records the given action to chrome.metricsPrivate. */
export function record(action: UserAction) {
if (!chrome.metricsPrivate) {
return;
}
if (!actionsMetric) {
actionsMetric = {
'metricName': 'PDF.Actions',
'type': chrome.metricsPrivate.MetricTypeType.HISTOGRAM_LOG,
'min': 1,
'max': UserAction.NUMBER_OF_ACTIONS,
'buckets': UserAction.NUMBER_OF_ACTIONS + 1,
};
}
chrome.metricsPrivate.recordValue(actionsMetric, action);
if (firstMap.has(action)) {
const firstAction = firstMap.get(action)!;
if (!firstActionRecorded.has(firstAction)) {
chrome.metricsPrivate.recordValue(actionsMetric, firstAction);
firstActionRecorded.add(firstAction);
}
}
}
/**
* Records when the user selects to turn on or off PDF OCR.
* @param userSelection the new UserSelection.
*/
export function recordPdfOcrUserSelection(pdfOcrAlwaysActive: boolean) {
// Need to divide Object.keys().length by 2 to get the enum size due to enum
// reverse mapping in TypeScript.
const enumSize = Object.keys(PdfOcrUserSelection).length / 2;
const enumValue = pdfOcrAlwaysActive ?
PdfOcrUserSelection.TURN_ON_ALWAYS_FROM_MORE_ACTIONS :
PdfOcrUserSelection.TURN_OFF_FROM_MORE_ACTIONS;
recordEnumeration('Accessibility.PdfOcr.UserSelection', enumValue, enumSize);
}
/** Records the given enumeration to chrome.metricsPrivate. */
export function recordEnumeration(
enumKey: string, enumValue: number, enumSize: number) {
if (!chrome.metricsPrivate) {
return;
}
chrome.metricsPrivate.recordEnumerationValue(enumKey, enumValue, enumSize);
}
export function resetForTesting() {
firstActionRecorded.clear();
actionsMetric = null;
}
let actionsMetric: chrome.metricsPrivate.MetricType|null = null;
const firstActionRecorded: Set<UserAction> = new Set();
/**
* Keep in sync with the values for enum ChromePDFViewerActions in
* tools/metrics/histograms/metadata/pdf/enums.xml.
* These values are persisted to logs. Entries should not be renumbered, removed
* or reused.
*
* User Actions that can be recorded by calling record.
* The *_FIRST values are recorded automaticlly,
* eg. record(...ROTATE) will also record ROTATE_FIRST
* on the first instance.
*/
export enum UserAction {
// Recorded when the document is first loaded. This event serves as
// denominator to determine percentages of documents in which an action was
// taken as well as average number of each action per document.
DOCUMENT_OPENED = 0,
// Recorded when the document is rotated clockwise or counter-clockwise.
ROTATE_FIRST = 1,
ROTATE = 2,
FIT_TO_WIDTH_FIRST = 3,
FIT_TO_WIDTH = 4,
FIT_TO_PAGE_FIRST = 5,
FIT_TO_PAGE = 6,
// Recorded when a bookmark is followed.
FOLLOW_BOOKMARK_FIRST = 9,
FOLLOW_BOOKMARK = 10,
// Recorded when the page selection is used to navigate to another page.
PAGE_SELECTOR_NAVIGATE_FIRST = 11,
PAGE_SELECTOR_NAVIGATE = 12,
// Recorded when the user triggers a save of the document.
SAVE_FIRST = 13,
SAVE = 14,
// Recorded when the user triggers a save of the document and the document
// has been modified by annotations.
SAVE_WITH_ANNOTATION_FIRST = 15,
SAVE_WITH_ANNOTATION = 16,
PRINT_FIRST = 17,
PRINT = 18,
ENTER_ANNOTATION_MODE_FIRST = 19,
ENTER_ANNOTATION_MODE = 20,
EXIT_ANNOTATION_MODE_FIRST = 21,
EXIT_ANNOTATION_MODE = 22,
// Recorded when a pen stroke is made.
ANNOTATE_STROKE_TOOL_PEN_FIRST = 23,
ANNOTATE_STROKE_TOOL_PEN = 24,
// Recorded when an eraser stroke is made.
ANNOTATE_STROKE_TOOL_ERASER_FIRST = 25,
ANNOTATE_STROKE_TOOL_ERASER = 26,
// Recorded when a highlighter stroke is made.
ANNOTATE_STROKE_TOOL_HIGHLIGHTER_FIRST = 27,
ANNOTATE_STROKE_TOOL_HIGHLIGHTER = 28,
// Recorded when a stroke is made using touch.
ANNOTATE_STROKE_DEVICE_TOUCH_FIRST = 29,
ANNOTATE_STROKE_DEVICE_TOUCH = 30,
// Recorded when a stroke is made using mouse.
ANNOTATE_STROKE_DEVICE_MOUSE_FIRST = 31,
ANNOTATE_STROKE_DEVICE_MOUSE = 32,
// Recorded when a stroke is made using pen.
ANNOTATE_STROKE_DEVICE_PEN_FIRST = 33,
ANNOTATE_STROKE_DEVICE_PEN = 34,
// Recorded when two-up view mode is enabled.
TWO_UP_VIEW_ENABLE_FIRST = 35,
TWO_UP_VIEW_ENABLE = 36,
// Recorded when two-up view mode is disabled.
TWO_UP_VIEW_DISABLE_FIRST = 37,
TWO_UP_VIEW_DISABLE = 38,
// Recorded when zoom in button is clicked.
ZOOM_IN_FIRST = 39,
ZOOM_IN = 40,
// Recorded when zoom out button is clicked.
ZOOM_OUT_FIRST = 41,
ZOOM_OUT = 42,
// Recorded when the custom zoom input field is modified.
ZOOM_CUSTOM_FIRST = 43,
ZOOM_CUSTOM = 44,
// Recorded when a thumbnail is used for navigation.
THUMBNAIL_NAVIGATE_FIRST = 45,
THUMBNAIL_NAVIGATE = 46,
// Recorded when the user triggers a save of the document and the document
// has never been modified.
SAVE_ORIGINAL_ONLY_FIRST = 47,
SAVE_ORIGINAL_ONLY = 48,
// Recorded when the user triggers a save of the original document, even
// though the document has been modified.
SAVE_ORIGINAL_FIRST = 49,
SAVE_ORIGINAL = 50,
// Recorded when the user triggers a save of the edited document.
SAVE_EDITED_FIRST = 51,
SAVE_EDITED = 52,
// Recorded when the sidenav menu button is clicked.
TOGGLE_SIDENAV_FIRST = 53,
TOGGLE_SIDENAV = 54,
// Recorded when the thumbnails button in the sidenav is clicked.
SELECT_SIDENAV_THUMBNAILS_FIRST = 55,
SELECT_SIDENAV_THUMBNAILS = 56,
// Recorded when the outline button in the sidenav is clicked.
SELECT_SIDENAV_OUTLINE_FIRST = 57,
SELECT_SIDENAV_OUTLINE = 58,
// Recorded when the show/hide annotations overflow menu item is clicked.
TOGGLE_DISPLAY_ANNOTATIONS_FIRST = 59,
TOGGLE_DISPLAY_ANNOTATIONS = 60,
// Recorded when the present menu item is clicked.
PRESENT_FIRST = 61,
PRESENT = 62,
// Recorded when the document properties menu item is clicked.
PROPERTIES_FIRST = 63,
PROPERTIES = 64,
// Recorded when the attachment button in the sidenav is clicked.
SELECT_SIDENAV_ATTACHMENT_FIRST = 65,
SELECT_SIDENAV_ATTACHMENT = 66,
NUMBER_OF_ACTIONS = 67,
}
function createFirstMap(): Map<UserAction, UserAction> {
const entries = (Object.entries(UserAction) as Array<[string, number]>)
.filter(x => Number.isInteger(x[1]))
.sort((a, b) => a[1] - b[1]);
// Exclude the first and last entries (DOCUMENT_OPENED, and NUMBER_OF_ACTIONS)
// which don't have an equivalent "_FIRST" UserAction.
const entriesWithFirst = entries.slice(1, entries.length - 1);
const map = new Map();
for (let i = 0; i < entriesWithFirst.length; i += 2) {
map.set(entriesWithFirst[i + 1][1], entriesWithFirst[i][1]);
}
return map;
}
// Map from UserAction to the 'FIRST' action. These metrics are recorded
// by PDFMetrics.log the first time each corresponding action occurs.
const firstMap: Map<UserAction, UserAction> = createFirstMap();