diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2023-08-09 13:09:54 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2023-10-16 13:38:18 +0000 |
commit | acbcf08a6dffdfe90a6eaf661fcd6923f0de2447 (patch) | |
tree | 749564d8cf9b3d49cdae1cce9ec8ce0602900f1c /chromium/chrome/browser/resources/pdf | |
parent | 266cfa0fb83513250bcefd8234e0916c195a4b2e (diff) |
BASELINE: Update Chromium to 114.0.5735.248
Change-Id: Ie7ddd5d87175d4bde196f774c742cdbb9d5d311a
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/495463
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/chrome/browser/resources/pdf')
10 files changed, 344 insertions, 292 deletions
diff --git a/chromium/chrome/browser/resources/pdf/BUILD.gn b/chromium/chrome/browser/resources/pdf/BUILD.gn index 64f37d5fc1a..cb228efb9bc 100644 --- a/chromium/chrome/browser/resources/pdf/BUILD.gn +++ b/chromium/chrome/browser/resources/pdf/BUILD.gn @@ -2,62 +2,145 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//chrome/common/features.gni") import("//components/services/screen_ai/buildflags/features.gni") import("//pdf/features.gni") -import("//tools/grit/grit_rule.gni") -import("//tools/grit/preprocess_if_expr.gni") -import("//tools/polymer/css_to_wrapper.gni") -import("//tools/polymer/html_to_wrapper.gni") -import("//tools/typescript/ts_library.gni") +import("//ui/webui/resources/tools/build_webui.gni") import("//ui/webui/resources/tools/generate_grd.gni") import("//ui/webui/resources/tools/optimize_webui.gni") -import("./pdf.gni") assert(enable_pdf, "enable_pdf check failed") -preprocess_folder = "${target_gen_dir}/preprocessed" -tsc_folder = "tsc" +build_webui("build") { + static_files = [ + "index.css", + "index.html", + "index_print.html", + ] + if (enable_ink) { + static_files += [ "ink/index.html" ] + } -preprocess_if_expr("preprocess") { - out_folder = preprocess_folder - defines = [ - "enable_ink=$enable_ink", - "enable_screen_ai_service=$enable_screen_ai_service", + web_component_files = [ + "elements/viewer-bookmark.ts", + "elements/viewer-document-outline.ts", + "elements/viewer-download-controls.ts", + "elements/viewer-error-dialog.ts", + "elements/viewer-page-selector.ts", + "elements/viewer-password-dialog.ts", + "elements/viewer-pdf-sidenav.ts", + "elements/viewer-properties-dialog.ts", + "elements/viewer-thumbnail-bar.ts", + "elements/viewer-thumbnail.ts", + "elements/viewer-toolbar.ts", + "pdf_viewer.ts", + + # Files only used in Print Preview's PDF Viewer UI. + "elements/viewer-page-indicator.ts", + "elements/viewer-zoom-button.ts", + "elements/viewer-zoom-toolbar.ts", + "pdf_viewer_print.ts", ] - in_files = ts_files + html_files + icons_html_files + css_files -} -html_to_wrapper("html_wrapper_files") { - deps = [ ":preprocess" ] - in_folder = preprocess_folder - out_folder = preprocess_folder - in_files = html_files + icons_html_files - minify = optimize_webui -} + if (enable_ink) { + web_component_files += [ + "elements/viewer-annotations-bar.ts", + "elements/viewer-annotations-mode-dialog.ts", + "elements/viewer-ink-host.ts", + "elements/viewer-pen-options.ts", + "elements/viewer-toolbar-dropdown.ts", + ] + } -css_to_wrapper("css_wrapper_files") { - deps = [ ":preprocess" ] - in_folder = preprocess_folder - out_folder = preprocess_folder - in_files = css_files - minify = optimize_webui -} + non_web_component_files = [ + "bookmark_type.ts", + "browser_api.ts", + "constants.ts", + "controller.ts", + "gesture_detector.ts", + "internal_plugin.ts", + "local_storage_proxy.ts", + "main.ts", + "metrics.ts", + "navigator.ts", + "open_pdf_params_parser.ts", + "pdf_print_wrapper.ts", + "pdf_scripting_api.ts", + "pdf_viewer_base.ts", + "pdf_viewer_utils.ts", + "pdf_viewer_wrapper.ts", + "pdf_internal_plugin_wrapper.ts", + "swipe_detector.ts", + "viewport.ts", + "viewport_scroller.ts", + "zoom_manager.ts", + + # Files only used in Print Preview's PDF viewer UI. + "main_print.ts", + "toolbar_manager.ts", + ] -if (optimize_webui) { - build_manifest = "build_manifest.json" + if (enable_ink) { + non_web_component_files += [ + "annotation_tool.ts", + "ink/ink_api.ts", + "ink_controller.ts", + ] + } - optimize_webui("build") { - host = "chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai" - input = rebase_path("$target_gen_dir/$tsc_folder", root_build_dir) - js_module_in_files = [ + if (enable_screen_ai_service) { + non_web_component_files += [ "pdf_viewer_private_proxy.ts" ] + } + + css_files = [ + "elements/pdf-shared.css", + "elements/shared-vars.css", + "pdf_viewer_shared_style.css", + ] + + icons_html_files = [ "elements/icons.html" ] + + html_to_wrapper_scheme = "chrome" + + # TypeScript Compiler parameters + ts_composite = true + ts_definitions = [ + "//tools/typescript/definitions/chrome_event.d.ts", + "//tools/typescript/definitions/content_settings.d.ts", + "//tools/typescript/definitions/file_system.d.ts", + "//tools/typescript/definitions/metrics_private.d.ts", + "//tools/typescript/definitions/mime_handler_private.d.ts", + "//tools/typescript/definitions/pdf_viewer_private.d.ts", + "//tools/typescript/definitions/pending.d.ts", + "//tools/typescript/definitions/resources_private.d.ts", + "//tools/typescript/definitions/runtime.d.ts", + "//tools/typescript/definitions/tabs.d.ts", + "//tools/typescript/definitions/windows.d.ts", + ] + if (enable_ink) { + ts_definitions += + [ "//chrome/browser/resources/pdf/ink/drawing_canvas.d.ts" ] + } + ts_deps = [ + "//third_party/polymer/v3_0:library", + "//ui/webui/resources/cr_elements:build_ts", + "//ui/webui/resources/js:build_ts", + ] + + # grd file generation parameters + grd_prefix = "pdf" + extra_grdp_deps = [ ":build_internal_plugin_grdp" ] + extra_grdp_files = [ "$target_gen_dir/internal_plugin_resources.grdp" ] + grd_resource_path_prefix = "pdf" + + # Optimization parameters + optimize = optimize_webui + if (optimize) { + optimize_webui_host = "chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai" + optimize_webui_in_files = [ "pdf_viewer_wrapper.js", "pdf_print_wrapper.js", ] - out_manifest = "$target_gen_dir/$build_manifest" - - deps = [ ":build_ts" ] - excludes = [ + optimize_webui_excludes = [ "browser_api.js", # Exclude pdf_scripting_api so that Print Preview can import @@ -65,14 +148,20 @@ if (optimize_webui) { "pdf_scripting_api.js", ] if (enable_ink) { - excludes += [ + optimize_webui_excludes += [ "ink/drawing_canvas_externs.js", "ink/ink_api.js", ] } + extra_grdp_deps += [ ":build_excluded_grdp" ] + extra_grdp_files += [ "$target_gen_dir/excluded_resources.grdp" ] } } +# Extra grdp build targets + +tsc_folder = "tsc" + # This script is injected by `pdf::PluginResponseWriter`, and must stand alone. # Consequently, it must always be rolled up by `optimize_webui()`. build_internal_plugin_manifest = "build_internal_plugin_manifest.json" @@ -86,6 +175,14 @@ optimize_webui("build_internal_plugin") { excludes = [ "browser_api.js" ] } +generate_grd("build_internal_plugin_grdp") { + manifest_files = [ "$target_gen_dir/$build_internal_plugin_manifest" ] + deps = [ ":build_internal_plugin" ] + grd_prefix = "pdf" + resource_path_prefix = "pdf" + out_grd = "$target_gen_dir/internal_plugin_resources.grdp" +} + if (optimize_webui) { # Need to manually register files that are excluded from the optimized bundle. generate_grd("build_excluded_grdp") { @@ -107,79 +204,3 @@ if (optimize_webui) { resource_path_prefix = "pdf" } } - -grit("resources") { - defines = chrome_grit_defines + [ "enable_ink=$enable_ink" ] - - enable_input_discovery_for_gn_analyze = false - source = "$target_gen_dir/resources.grd" - deps = [ ":build_grd" ] - - outputs = [ - "grit/pdf_resources.h", - "grit/pdf_resources_map.cc", - "grit/pdf_resources_map.h", - "pdf_resources.pak", - ] - output_dir = "$root_gen_dir/chrome" -} - -ts_library("build_ts") { - root_dir = preprocess_folder - out_dir = "$target_gen_dir/$tsc_folder" - tsconfig_base = "tsconfig_base.json" - composite = true - - in_files = ts_files + html_wrapper_files + css_wrapper_files - - manifest_excludes = [ "pdf_internal_plugin_wrapper.js" ] - - definitions = ts_definitions - - deps = [ - "//third_party/polymer/v3_0:library", - "//ui/webui/resources/cr_elements:build_ts", - "//ui/webui/resources/js:build_ts", - ] - extra_deps = [ - ":css_wrapper_files", - ":html_wrapper_files", - ":preprocess", - ] -} - -generate_grd("build_grd") { - input_files = [ - "index.css", - "index.html", - "index_print.html", - ] - if (enable_ink) { - input_files += [ "ink/index.html" ] - } - input_files_base_dir = rebase_path(".", "//") - - if (optimize_webui) { - deps = [ - ":build", - ":build_excluded_grdp", - ] - resource_path_rewrites = [ - "pdf_viewer_wrapper.rollup.js|pdf_viewer_wrapper.js", - "pdf_print_wrapper.rollup.js|pdf_print_wrapper.js", - ] - manifest_files = [ "$target_gen_dir/$build_manifest" ] - grdp_files = [ "$target_gen_dir/excluded_resources.grdp" ] - } else { - deps = [ ":build_ts" ] - manifest_files = - filter_include(get_target_outputs(":build_ts"), [ "*.manifest" ]) - } - - deps += [ ":build_internal_plugin" ] - manifest_files += [ "$target_gen_dir/$build_internal_plugin_manifest" ] - - grd_prefix = "pdf" - out_grd = "$target_gen_dir/resources.grd" - resource_path_prefix = "pdf" -} diff --git a/chromium/chrome/browser/resources/pdf/constants.ts b/chromium/chrome/browser/resources/pdf/constants.ts index d56e7f5c55e..9969a477156 100644 --- a/chromium/chrome/browser/resources/pdf/constants.ts +++ b/chromium/chrome/browser/resources/pdf/constants.ts @@ -29,12 +29,13 @@ export interface DocumentMetadata { version: string; } -/** Enumeration of page fitting types. */ +/** Enumeration of page fitting types and bounding box fitting types. */ export enum FittingType { NONE = 'none', FIT_TO_PAGE = 'fit-to-page', FIT_TO_WIDTH = 'fit-to-width', FIT_TO_HEIGHT = 'fit-to-height', + FIT_TO_BOUNDING_BOX = 'fit-to-bounding-box', } export interface NamedDestinationMessageData { @@ -58,6 +59,13 @@ export interface Point { y: number; } +export interface Rect { + x: number; + y: number; + width: number; + height: number; +} + export type ExtendedKeyEvent = KeyboardEvent&{ fromScriptingAPI?: boolean, fromPlugin?: boolean, diff --git a/chromium/chrome/browser/resources/pdf/controller.ts b/chromium/chrome/browser/resources/pdf/controller.ts index b8cf630f24d..2f0b4a66957 100644 --- a/chromium/chrome/browser/resources/pdf/controller.ts +++ b/chromium/chrome/browser/resources/pdf/controller.ts @@ -5,7 +5,7 @@ import {assert} from 'chrome://resources/js/assert_ts.js'; import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js'; -import {NamedDestinationMessageData, SaveRequestType} from './constants.js'; +import {NamedDestinationMessageData, Rect, SaveRequestType} from './constants.js'; import {PdfPluginElement} from './internal_plugin.js'; import {PinchPhase, Viewport} from './viewport.js'; @@ -322,6 +322,13 @@ export class PluginController implements ContentController { this.postMessage_({type: 'loadPreviewPage', url: url, index: index}); } + getPageBoundingBox(page: number): Promise<Rect> { + return this.postMessageWithReply_({ + type: 'getPageBoundingBox', + page, + }); + } + getPasswordComplete(password: string) { this.postMessage_({type: 'getPasswordComplete', password: password}); } diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar.html b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar.html index 972713e4208..66e59117d89 100644 --- a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar.html +++ b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar.html @@ -184,6 +184,16 @@ padding-inline-start: 12px; } + /* For more info, see https://webaim.org/techniques/css/invisiblecontent/ */ + .only-visible-to-screen-reader { + height: 1px; + left: -10000px; + overflow: hidden; + position: absolute; + top: auto; + width: 1px; + } + .check-container { margin-inline-end: 12px; width: 16px; @@ -296,7 +306,8 @@ <if expr="enable_screen_ai_service"> <template is="dom-if" if="[[pdfOcrEnabled]]"> <button id="pdf-ocr-button" - class="dropdown-item" on-click="onPdfOcrClick_" role="checkbox" + class="dropdown-item only-visible-to-screen-reader" + on-click="onPdfOcrClick_" role="checkbox" aria-checked="[[getAriaChecked_(pdfOcrAlwaysActive_)]]"> <span class="check-container"> <iron-icon icon="pdf:check" hidden="[[!pdfOcrAlwaysActive_]]"> diff --git a/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.ts b/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.ts index 95d6213a952..dd027c1f180 100644 --- a/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.ts +++ b/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.ts @@ -3,33 +3,54 @@ // found in the LICENSE file. import {assert} from 'chrome://resources/js/assert_ts.js'; -import {FittingType, NamedDestinationMessageData, Point} from './constants.js'; + +import {FittingType, NamedDestinationMessageData, Point, Rect} from './constants.js'; import {Size} from './viewport.js'; export interface OpenPdfParams { + boundingBox?: Rect; + page?: number; + position?: Point; url?: string; - zoom?: number; view?: FittingType; viewPosition?: number; - position?: Point; - page?: number; + zoom?: number; +} + +export enum ViewMode { + FIT = 'fit', + FIT_B = 'fitb', + FIT_BH = 'fitbh', + FIT_BV = 'fitbv', + FIT_H = 'fith', + FIT_R = 'fitr', + FIT_V = 'fitv', + XYZ = 'xyz', } type GetNamedDestinationCallback = (name: string) => Promise<NamedDestinationMessageData>; +type GetPageBoundingBoxCallback = (page: number) => Promise<Rect>; + // Parses the open pdf parameters passed in the url to set initial viewport // settings for opening the pdf. export class OpenPdfParamsParser { private getNamedDestinationCallback_: GetNamedDestinationCallback; + private getPageBoundingBoxCallback_: GetPageBoundingBoxCallback; private viewportDimensions_?: Size; /** * @param getNamedDestinationCallback Function called to fetch information for * a named destination. + * @param getPageBoundingBoxCallback Function called to fetch information for + * a page's bounding box. */ - constructor(getNamedDestinationCallback: GetNamedDestinationCallback) { + constructor( + getNamedDestinationCallback: GetNamedDestinationCallback, + getPageBoundingBoxCallback: GetPageBoundingBoxCallback) { this.getNamedDestinationCallback_ = getNamedDestinationCallback; + this.getPageBoundingBoxCallback_ = getPageBoundingBoxCallback; } /** @@ -84,29 +105,52 @@ export class OpenPdfParamsParser { /** * Parse view parameter of open PDF parameters. The PDF should be opened at * the specified fitting type mode and position. + * @param paramValue Params to parse. + * @param pageNumber Page number for bounding box, if there is a fit bounding + * box param. * @return Map with view parameters (view and viewPosition). */ - private parseViewParam_(paramValue: string): OpenPdfParams { + private async parseViewParam_(paramValue: string, pageNumber: number): + Promise<OpenPdfParams> { const viewModeComponents = paramValue.toLowerCase().split(','); - if (viewModeComponents.length < 1) { + if (viewModeComponents.length === 0) { return {}; } const params: OpenPdfParams = {}; const viewMode = viewModeComponents[0]; - let acceptsPositionParam; - if (viewMode === 'fit') { - params['view'] = FittingType.FIT_TO_PAGE; - acceptsPositionParam = false; - } else if (viewMode === 'fith') { - params['view'] = FittingType.FIT_TO_WIDTH; - acceptsPositionParam = true; - } else if (viewMode === 'fitv') { - params['view'] = FittingType.FIT_TO_HEIGHT; - acceptsPositionParam = true; + let acceptsPositionParam = false; + switch (viewMode) { + case ViewMode.FIT: + params['view'] = FittingType.FIT_TO_PAGE; + break; + case ViewMode.FIT_H: + params['view'] = FittingType.FIT_TO_WIDTH; + acceptsPositionParam = true; + break; + case ViewMode.FIT_V: + params['view'] = FittingType.FIT_TO_HEIGHT; + acceptsPositionParam = true; + break; + case ViewMode.FIT_B: + params['view'] = FittingType.FIT_TO_BOUNDING_BOX; + // pageNumber is 1-indexed, but PDF Viewer is 0-indexed. + params['boundingBox'] = + await this.getPageBoundingBoxCallback_(pageNumber - 1); + break; + case ViewMode.FIT_BH: + case ViewMode.FIT_BV: + // Not implemented yet, do nothing. + break; + case ViewMode.FIT_R: + case ViewMode.XYZ: + // Should have already been handled in `parseNameddestViewParam_()`. + break; + default: + // Invalid view parameter, do nothing. } - if (!acceptsPositionParam || viewModeComponents.length < 2) { + if (!acceptsPositionParam || viewModeComponents.length === 1) { return params; } @@ -120,14 +164,18 @@ export class OpenPdfParamsParser { /** * Parse view parameters which come from nameddest. + * @param paramValue Params to parse. + * @param pageNumber Page number for bounding box, if there is a fit bounding + * box param. * @return Map with view parameters. */ - private parseNameddestViewParam_(paramValue: string): OpenPdfParams { + private async parseNameddestViewParam_( + paramValue: string, pageNumber: number): Promise<OpenPdfParams> { const viewModeComponents = paramValue.toLowerCase().split(','); const viewMode = viewModeComponents[0]; const params: OpenPdfParams = {}; - if (viewMode === 'xyz' && viewModeComponents.length === 4) { + if (viewMode === ViewMode.XYZ && viewModeComponents.length === 4) { const x = parseFloat(viewModeComponents[1]); const y = parseFloat(viewModeComponents[2]); const zoom = parseFloat(viewModeComponents[3]); @@ -145,7 +193,7 @@ export class OpenPdfParamsParser { return params; } - if (viewMode === 'fitr' && viewModeComponents.length === 5) { + if (viewMode === ViewMode.FIT_R && viewModeComponents.length === 5) { assert(this.viewportDimensions_ !== undefined); let x1 = parseFloat(viewModeComponents[1]); let y1 = parseFloat(viewModeComponents[2]); @@ -169,7 +217,7 @@ export class OpenPdfParamsParser { return params; } - return this.parseViewParam_(paramValue); + return this.parseViewParam_(paramValue, pageNumber); } /** Parse the parameters encoded in the fragment of a URL. */ @@ -241,16 +289,23 @@ export class OpenPdfParamsParser { const urlParams = this.parseUrlParams_(url); + let pageNumber; if (urlParams.has('page')) { // |pageNumber| is 1-based, but goToPage() take a zero-based page index. - const pageNumber = parseInt(urlParams.get('page')!, 10); + pageNumber = parseInt(urlParams.get('page')!, 10); if (!Number.isNaN(pageNumber) && pageNumber > 0) { params['page'] = pageNumber - 1; } } + if (!pageNumber || pageNumber < 1) { + pageNumber = 1; + } + if (urlParams.has('view')) { - Object.assign(params, this.parseViewParam_(urlParams.get('view')!)); + Object.assign( + params, + await this.parseViewParam_(urlParams.get('view')!, pageNumber!)); } if (urlParams.has('zoom')) { @@ -263,16 +318,17 @@ export class OpenPdfParamsParser { if (data.pageNumber !== -1) { params.page = data.pageNumber; + pageNumber = data.pageNumber; } if (data.namedDestinationView) { Object.assign( - params, this.parseNameddestViewParam_(data.namedDestinationView)); + params, + await this.parseNameddestViewParam_( + data.namedDestinationView, pageNumber!)); } - return params; } - - return Promise.resolve(params); + return params; } } diff --git a/chromium/chrome/browser/resources/pdf/pdf.gni b/chromium/chrome/browser/resources/pdf/pdf.gni deleted file mode 100644 index 4e8195d456a..00000000000 --- a/chromium/chrome/browser/resources/pdf/pdf.gni +++ /dev/null @@ -1,125 +0,0 @@ -# Copyright 2022 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//components/services/screen_ai/buildflags/features.gni") -import("//pdf/features.gni") - -# Files holding a Polymer element definition AND have an equivalent .html file -web_component_files = [ - "elements/viewer-bookmark.ts", - "elements/viewer-document-outline.ts", - "elements/viewer-download-controls.ts", - "elements/viewer-error-dialog.ts", - "elements/viewer-page-selector.ts", - "elements/viewer-password-dialog.ts", - "elements/viewer-pdf-sidenav.ts", - "elements/viewer-properties-dialog.ts", - "elements/viewer-thumbnail-bar.ts", - "elements/viewer-thumbnail.ts", - "elements/viewer-toolbar.ts", - "pdf_viewer.ts", - - # Files only used in Print Preview's PDF Viewer UI. - "elements/viewer-page-indicator.ts", - "elements/viewer-zoom-button.ts", - "elements/viewer-zoom-toolbar.ts", - "pdf_viewer_print.ts", -] - -if (enable_ink) { - web_component_files += [ - "elements/viewer-annotations-bar.ts", - "elements/viewer-annotations-mode-dialog.ts", - "elements/viewer-ink-host.ts", - "elements/viewer-pen-options.ts", - "elements/viewer-toolbar-dropdown.ts", - ] -} - -# Files that are passed as input to html_to_wrapper(). -html_files = [] -foreach(f, web_component_files) { - html_files += [ string_replace(f, ".ts", ".html") ] -} - -icons_html_files = [ "elements/icons.html" ] - -# Files that are generated by html_to_wrapper(). -html_wrapper_files = [] -foreach(f, html_files + icons_html_files) { - html_wrapper_files += [ f + ".ts" ] -} - -# Files that are passed as input to css_to_wrapper(). -css_files = [ - "elements/pdf-shared.css", - "elements/shared-vars.css", - "pdf_viewer_shared_style.css", -] - -# Files that are generated by css_to_wrapper(). -css_wrapper_files = [] -foreach(f, css_files) { - css_wrapper_files += [ f + ".ts" ] -} - -# Files to pass directly to preprocess_if_expr(). -ts_files = [ - "bookmark_type.ts", - "browser_api.ts", - "constants.ts", - "controller.ts", - "gesture_detector.ts", - "internal_plugin.ts", - "local_storage_proxy.ts", - "main.ts", - "metrics.ts", - "navigator.ts", - "open_pdf_params_parser.ts", - "pdf_print_wrapper.ts", - "pdf_scripting_api.ts", - "pdf_viewer_base.ts", - "pdf_viewer_utils.ts", - "pdf_viewer_wrapper.ts", - "pdf_internal_plugin_wrapper.ts", - "swipe_detector.ts", - "viewport.ts", - "viewport_scroller.ts", - "zoom_manager.ts", - - # Files only used in Print Preview's PDF viewer UI. - "main_print.ts", - "toolbar_manager.ts", -] -ts_files += web_component_files - -if (enable_ink) { - ts_files += [ - "annotation_tool.ts", - "ink/ink_api.ts", - "ink_controller.ts", - ] -} - -if (enable_screen_ai_service) { - ts_files += [ "pdf_viewer_private_proxy.ts" ] -} - -ts_definitions = [ - "//tools/typescript/definitions/chrome_event.d.ts", - "//tools/typescript/definitions/content_settings.d.ts", - "//tools/typescript/definitions/file_system.d.ts", - "//tools/typescript/definitions/metrics_private.d.ts", - "//tools/typescript/definitions/mime_handler_private.d.ts", - "//tools/typescript/definitions/pdf_viewer_private.d.ts", - "//tools/typescript/definitions/pending.d.ts", - "//tools/typescript/definitions/resources_private.d.ts", - "//tools/typescript/definitions/runtime.d.ts", - "//tools/typescript/definitions/tabs.d.ts", - "//tools/typescript/definitions/windows.d.ts", -] - -if (enable_ink) { - ts_definitions += [ "//chrome/browser/resources/pdf/ink/drawing_canvas.d.ts" ] -} diff --git a/chromium/chrome/browser/resources/pdf/pdf_viewer_base.ts b/chromium/chrome/browser/resources/pdf/pdf_viewer_base.ts index e336e11b410..c7cc31b1f34 100644 --- a/chromium/chrome/browser/resources/pdf/pdf_viewer_base.ts +++ b/chromium/chrome/browser/resources/pdf/pdf_viewer_base.ts @@ -149,11 +149,6 @@ export abstract class PdfViewerBaseElement extends PolymerElement { record(UserAction.DOCUMENT_OPENED); - // Parse open pdf parameters. - this.paramsParser = new OpenPdfParamsParser(destination => { - return PluginController.getInstance().getNamedDestination(destination); - }); - // Create the viewport. const defaultZoom = this.browserApi!.getZoomBehavior() === ZoomBehavior.MANAGE ? @@ -190,6 +185,16 @@ export abstract class PdfViewerBaseElement extends PolymerElement { pluginController.isActive = true; this.currentController = pluginController; + // Parse open pdf parameters. + const getNamedDestinationCallback = (destination: string) => { + return PluginController.getInstance().getNamedDestination(destination); + }; + const getPageBoundingBoxCallback = (page: number) => { + return PluginController.getInstance().getPageBoundingBox(page); + }; + this.paramsParser = new OpenPdfParamsParser( + getNamedDestinationCallback, getPageBoundingBoxCallback); + this.tracker.add( pluginController.getEventTarget(), PluginControllerEventType.PLUGIN_MESSAGE, @@ -432,14 +437,22 @@ export abstract class PdfViewerBaseElement extends PolymerElement { if (params.position) { this.viewport_.goToPageAndXy( - params.page ? params.page : 0, params.position.x, params.position.y); + params.page || 0, params.position.x, params.position.y); } else if (params.page) { this.viewport_.goToPage(params.page); } if (params.view) { this.isUserInitiatedEvent = false; - this.viewport_.setFittingType(params.view); + let fittingTypeParams; + if (params.view === FittingType.FIT_TO_BOUNDING_BOX) { + assert(params.boundingBox); + fittingTypeParams = { + page: params.page || 0, + boundingBox: params.boundingBox, + }; + } + this.viewport_.setFittingType(params.view, fittingTypeParams); this.forceFit(params.view); if (params.viewPosition) { const zoomedPositionShift = diff --git a/chromium/chrome/browser/resources/pdf/pdf_viewer_wrapper.ts b/chromium/chrome/browser/resources/pdf/pdf_viewer_wrapper.ts index e2a68a8c055..53020dae03e 100644 --- a/chromium/chrome/browser/resources/pdf/pdf_viewer_wrapper.ts +++ b/chromium/chrome/browser/resources/pdf/pdf_viewer_wrapper.ts @@ -9,7 +9,7 @@ export {AnnotationTool} from './annotation_tool.js'; // </if> export {Bookmark} from './bookmark_type.js'; export {BrowserApi, ZoomBehavior} from './browser_api.js'; -export {FittingType, Point, SaveRequestType} from './constants.js'; +export {FittingType, Point, Rect, SaveRequestType} from './constants.js'; export {PluginController} from './controller.js'; export {ChangePageAndXyDetail, ChangePageDetail, ChangePageOrigin, ChangeZoomDetail, NavigateDetail, ViewerBookmarkElement} from './elements/viewer-bookmark.js'; export {ViewerDocumentOutlineElement} from './elements/viewer-document-outline.js'; @@ -31,7 +31,7 @@ export {GestureDetector, PinchEventDetail} from './gesture_detector.js'; export {PdfPluginElement} from './internal_plugin.js'; export {record, recordFitTo, resetForTesting, UserAction} from './metrics.js'; export {NavigatorDelegate, PdfNavigator, WindowOpenDisposition} from './navigator.js'; -export {OpenPdfParamsParser} from './open_pdf_params_parser.js'; +export {OpenPdfParamsParser, ViewMode} from './open_pdf_params_parser.js'; export {getFilenameFromURL, PdfViewerElement} from './pdf_viewer.js'; export {PdfViewerBaseElement} from './pdf_viewer_base.js'; export {shouldIgnoreKeyEvents} from './pdf_viewer_utils.js'; diff --git a/chromium/chrome/browser/resources/pdf/tsconfig_base.json b/chromium/chrome/browser/resources/pdf/tsconfig_base.json deleted file mode 100644 index afa07315728..00000000000 --- a/chromium/chrome/browser/resources/pdf/tsconfig_base.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../../../tools/typescript/tsconfig_base.json", - "compilerOptions": { - "noUncheckedIndexedAccess": false, - "noUnusedLocals": false, - "strictPropertyInitialization": false - } -} diff --git a/chromium/chrome/browser/resources/pdf/viewport.ts b/chromium/chrome/browser/resources/pdf/viewport.ts index 79c9d8a3f0e..afa4aad66f4 100644 --- a/chromium/chrome/browser/resources/pdf/viewport.ts +++ b/chromium/chrome/browser/resources/pdf/viewport.ts @@ -8,7 +8,7 @@ import {EventTracker} from 'chrome://resources/js/event_tracker.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {hasKeyModifiers, isRTL} from 'chrome://resources/js/util_ts.js'; -import {ExtendedKeyEvent, FittingType, Point} from './constants.js'; +import {ExtendedKeyEvent, FittingType, Point, Rect} from './constants.js'; import {Gesture, GestureDetector, PinchEventDetail} from './gesture_detector.js'; import {PdfPluginElement} from './internal_plugin.js'; import {SwipeDetector, SwipeDirection} from './swipe_detector.js'; @@ -40,6 +40,11 @@ export interface Size { height: number; } +interface FittingTypeParams { + page: number; + boundingBox: Rect; +} + /** @return The area of the intersection of the rects */ function getIntersectionArea(rect1: ViewportRect, rect2: ViewportRect): number { const left = Math.max(rect1.x, rect2.x); @@ -604,6 +609,11 @@ export class Viewport implements ViewportInterface { * Save the current zoom and fitting type. */ saveZoomState() { + // Fitting to bounding box does not need to be saved, so set the fitting + // type to none. + if (this.fittingType_ === FittingType.FIT_TO_BOUNDING_BOX) { + this.setFittingType(FittingType.NONE); + } this.savedZoom_ = this.internalZoom_; this.savedFittingType_ = this.fittingType_; } @@ -901,7 +911,11 @@ export class Viewport implements ViewportInterface { return Math.max(zoom, 0); } - setFittingType(fittingType: FittingType) { + /** + * Set the fitting type and fit within the viewport accordingly. + * @param params Params required for fitting to the bounding box. + */ + setFittingType(fittingType: FittingType, params?: FittingTypeParams) { switch (fittingType) { case FittingType.FIT_TO_PAGE: this.fitToPage(); @@ -912,6 +926,10 @@ export class Viewport implements ViewportInterface { case FittingType.FIT_TO_HEIGHT: this.fitToHeight(); return; + case FittingType.FIT_TO_BOUNDING_BOX: + assert(params); + this.fitToBoundingBox_(params.page, params.boundingBox); + return; case FittingType.NONE: this.fittingType_ = fittingType; return; @@ -1021,6 +1039,56 @@ export class Viewport implements ViewportInterface { }); } + /** + * Zoom the viewport so that the bounding box of a page consumes the entire + * viewport. + * @param page The page to display. + * @param boundingBox The bounding box to fit to. + */ + private fitToBoundingBox_(page: number, boundingBox: Rect) { + // Ignore invalid bounding boxes, which can occur if the plugin fails to + // give a valid box. + if (!boundingBox.width || !boundingBox.height) { + return; + } + + this.fittingType_ = FittingType.FIT_TO_BOUNDING_BOX; + + // Use the smallest zoom that fits the full bounding box on screen. + const boundingBoxSize = { + width: boundingBox.width, + height: boundingBox.height, + }; + + const zoomFitToWidth = + this.computeFittingZoom_(boundingBoxSize, true, false); + const zoomFitToHeight = + this.computeFittingZoom_(boundingBoxSize, false, true); + const newZoom = this.clampZoom_(Math.min(zoomFitToWidth, zoomFitToHeight)); + this.mightZoom_(() => { + this.setZoomInternal_(newZoom); + }); + + // Calculate the position. + const pageInsetDimensions = this.getPageInsetDimensions(page); + const viewportSize = this.size; + const screenPosition: Point = { + x: pageInsetDimensions.x + boundingBox.x, + y: pageInsetDimensions.y + boundingBox.y, + }; + // Center the bounding box in the dimension that isn't fully zoomed in. + if (newZoom !== zoomFitToWidth) { + screenPosition.x -= + ((viewportSize.width / newZoom) - boundingBox.width) / 2; + } + if (newZoom !== zoomFitToHeight) { + screenPosition.y -= + ((viewportSize.height / newZoom) - boundingBox.height) / 2; + } + this.setPosition( + {x: screenPosition.x * newZoom, y: screenPosition.y * newZoom}); + } + /** Zoom out to the next predefined zoom level. */ zoomOut() { this.mightZoom_(() => { @@ -1361,6 +1429,7 @@ export class Viewport implements ViewportInterface { */ handleNavigateToDestination( page: number, x: number|undefined, y: number|undefined, zoom: number) { + // TODO(crbug.com/1430193): Handle view parameters and fitting types. if (zoom) { this.setZoom(zoom); } |