blob: 92c582acc8524db0508bb43044a507eab2488244 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {assert} from 'chrome://resources/js/assert.js';
import {getDeepActiveElement} from 'chrome://resources/js/util.js';
// <if expr="enable_pdf_ink2">
import type {Color} from './constants.js';
// </if>
import type {LayoutOptions, ViewportRect} from './viewport.js';
// <if expr="enable_pdf_ink2">
// LINT.IfChange(HighlighterOpacity)
const HIGHLIGHTER_OPACITY: number = 0.4;
// LINT.ThenChange(//pdf/pdf_ink_brush.cc:HighlighterOpacity)
// </if>
// <if expr="enable_pdf_save_to_drive">
const SAVE_TO_DRIVE_ACCOUNT_CHOOSER_URL: string =
'https://accounts.google.com/AccountChooser';
const SAVE_TO_DRIVE_CONSUMER_MANAGE_STORAGE_URL: string =
'https://one.google.com/storage' +
'?utm_source=drive' +
'&utm_medium=desktop' +
'&utm_campaign=error_dialog_oos';
const SAVE_TO_DRIVE_DASHER_MANAGE_STORAGE_URL: string =
'https://drive.google.com/drive/quota';
const SAVE_TO_DRIVE_DRIVE_URL: string = 'https://drive.google.com';
// </if>
export interface DocumentDimensionsMessageData {
type: string;
height: number;
width: number;
pageDimensions: ViewportRect[];
layoutOptions?: LayoutOptions;
}
export interface DestinationMessageData {
type: string;
page: number;
x: number;
y: number;
zoom: number;
}
export interface RequiredSaveResult {
fileName: string;
dataToSave: ArrayBuffer;
}
/**
* Determines if the event has the platform-equivalent of the Windows ctrl key
* modifier.
* @return Whether the event has the ctrl key modifier.
*/
export function hasCtrlModifier(e: KeyboardEvent): boolean {
let hasModifier = e.ctrlKey;
// <if expr="is_macosx">
hasModifier = e.metaKey; // AKA Command.
// </if>
return hasModifier;
}
/**
* Determines if the event has the platform-equivalent of the Windows ctrl key
* modifier, and only that modifier.
* @return Whether the event only has the ctrl key modifier.
*/
export function hasCtrlModifierOnly(e: KeyboardEvent): boolean {
let metaModifier = e.metaKey;
// <if expr="is_macosx">
metaModifier = e.ctrlKey;
// </if>
return hasCtrlModifier(e) && !e.shiftKey && !e.altKey && !metaModifier;
}
/**
* Whether keydown events should currently be ignored. Events are ignored when
* an editable element has focus, to allow for proper editing controls.
* @return Whether keydown events should be ignored.
*/
export function shouldIgnoreKeyEvents(): boolean {
const activeElement = getDeepActiveElement();
assert(activeElement);
return (activeElement as HTMLElement).isContentEditable ||
(activeElement.tagName === 'INPUT' &&
(activeElement as HTMLInputElement).type !== 'radio') ||
activeElement.tagName === 'TEXTAREA';
}
// <if expr="enable_pdf_ink2">
/**
* Blends `colorValue` with highlighter opacity on a white background.
* @param colorValue The red, green, or blue value of a color.
* @returns The new respective red, green, or blue value of a color that has
* been transformed using the highlighter transparency on a white background.
*/
export function blendHighlighterColorValue(colorValue: number): number {
return Math.round(
colorValue * HIGHLIGHTER_OPACITY + 255 * (1 - HIGHLIGHTER_OPACITY));
}
/**
* @param color The `Color` in RGB values.
* @returns A hex-coded color string, formatted as '#ffffff'.
*/
export function colorToHex(color: Color): string {
const rgb = [color.r, color.g, color.b]
.map(value => value.toString(16).padStart(2, '0'))
.join('');
return `#${rgb}`;
}
/**
* @param hex A hex-coded color string, formatted as '#ffffff'.
* @returns The `Color` in RGB values.
*/
export function hexToColor(hex: string): Color {
assert(/^#[0-9a-f]{6}$/.test(hex));
return {
r: Number.parseInt(hex.substring(1, 3), 16),
g: Number.parseInt(hex.substring(3, 5), 16),
b: Number.parseInt(hex.substring(5, 7), 16),
};
}
// </if>
/* Verifies that the array buffer is suitable for the beginning of a PDF.
*
* @param buffer The beginning of data for a PDF.
*/
export function verifyPdfHeader(buffer: ArrayBuffer) {
const MIN_FILE_SIZE = '%PDF1.0'.length;
// Verify the first bytes to make sure it's a PDF.
const bufView = new Uint8Array(buffer);
assert(bufView.length >= MIN_FILE_SIZE);
assert(
String.fromCharCode(
bufView[0]!, bufView[1]!, bufView[2]!, bufView[3]!) === '%PDF');
}
// <if expr="enable_pdf_save_to_drive">
function getChooserRequiredUrl(
accountEmail: string, redirectUrl: string): string {
const url = new URL(SAVE_TO_DRIVE_ACCOUNT_CHOOSER_URL);
url.searchParams.set('Email', accountEmail);
url.searchParams.set('faa', '1');
url.searchParams.set('continue', redirectUrl);
return url.href;
}
export function getSaveToDriveManageStorageUrl(
accountEmail: string, accountIsManaged: boolean): string {
const redirectUrl = accountIsManaged ?
SAVE_TO_DRIVE_DASHER_MANAGE_STORAGE_URL :
SAVE_TO_DRIVE_CONSUMER_MANAGE_STORAGE_URL;
return getChooserRequiredUrl(accountEmail, redirectUrl);
}
export function getSaveToDriveOpenInDriveUrl(
accountEmail: string, driveItemId: string): string {
const url = new URL(SAVE_TO_DRIVE_DRIVE_URL);
url.searchParams.set('action', 'locate');
url.searchParams.set('id', driveItemId);
return getChooserRequiredUrl(accountEmail, url.href);
}
// </if> enable_pdf_save_to_drive