Allow text-selection, but not copying, when enablePermissions
is set (PR 16320 follow-up)
This commit is contained in:
parent
1b79b0cd21
commit
8a9d7a18cc
@ -122,6 +122,8 @@ class PDFPageView {
|
|||||||
|
|
||||||
#renderingState = RenderingStates.INITIAL;
|
#renderingState = RenderingStates.INITIAL;
|
||||||
|
|
||||||
|
#textLayerMode = TextLayerMode.ENABLE;
|
||||||
|
|
||||||
#useThumbnailCanvas = {
|
#useThumbnailCanvas = {
|
||||||
initialOptionalContent: true,
|
initialOptionalContent: true,
|
||||||
regularAnnotations: true,
|
regularAnnotations: true,
|
||||||
@ -149,7 +151,7 @@ class PDFPageView {
|
|||||||
this._optionalContentConfigPromise =
|
this._optionalContentConfigPromise =
|
||||||
options.optionalContentConfigPromise || null;
|
options.optionalContentConfigPromise || null;
|
||||||
this.hasRestrictedScaling = false;
|
this.hasRestrictedScaling = false;
|
||||||
this.textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
|
this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
|
||||||
this.#annotationMode =
|
this.#annotationMode =
|
||||||
options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
|
options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
|
||||||
this.imageResourcesPath = options.imageResourcesPath || "";
|
this.imageResourcesPath = options.imageResourcesPath || "";
|
||||||
@ -798,7 +800,7 @@ class PDFPageView {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
!this.textLayer &&
|
!this.textLayer &&
|
||||||
this.textLayerMode !== TextLayerMode.DISABLE &&
|
this.#textLayerMode !== TextLayerMode.DISABLE &&
|
||||||
!pdfPage.isPureXfa
|
!pdfPage.isPureXfa
|
||||||
) {
|
) {
|
||||||
this._accessibilityManager ||= new TextAccessibilityManager();
|
this._accessibilityManager ||= new TextAccessibilityManager();
|
||||||
@ -807,6 +809,8 @@ class PDFPageView {
|
|||||||
highlighter: this._textHighlighter,
|
highlighter: this._textHighlighter,
|
||||||
accessibilityManager: this._accessibilityManager,
|
accessibilityManager: this._accessibilityManager,
|
||||||
isOffscreenCanvasSupported: this.isOffscreenCanvasSupported,
|
isOffscreenCanvasSupported: this.isOffscreenCanvasSupported,
|
||||||
|
enablePermissions:
|
||||||
|
this.#textLayerMode === TextLayerMode.ENABLE_PERMISSIONS,
|
||||||
});
|
});
|
||||||
div.append(this.textLayer.div);
|
div.append(this.textLayer.div);
|
||||||
}
|
}
|
||||||
|
@ -185,11 +185,6 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pdfViewer.enablePermissions .textLayer span {
|
|
||||||
user-select: none !important;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pdfPresentationMode .pdfViewer {
|
.pdfPresentationMode .pdfViewer {
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,6 @@ import { PDFRenderingQueue } from "./pdf_rendering_queue.js";
|
|||||||
import { SimpleLinkService } from "./pdf_link_service.js";
|
import { SimpleLinkService } from "./pdf_link_service.js";
|
||||||
|
|
||||||
const DEFAULT_CACHE_SIZE = 10;
|
const DEFAULT_CACHE_SIZE = 10;
|
||||||
const ENABLE_PERMISSIONS_CLASS = "enablePermissions";
|
|
||||||
|
|
||||||
const PagesCountLimit = {
|
const PagesCountLimit = {
|
||||||
FORCE_SCROLL_MODE_PAGE: 15000,
|
FORCE_SCROLL_MODE_PAGE: 15000,
|
||||||
@ -206,7 +205,7 @@ class PDFViewer {
|
|||||||
|
|
||||||
#containerTopLeft = null;
|
#containerTopLeft = null;
|
||||||
|
|
||||||
#copyCallbackBound = this.#copyCallback.bind(this);
|
#copyCallbackBound = null;
|
||||||
|
|
||||||
#enablePermissions = false;
|
#enablePermissions = false;
|
||||||
|
|
||||||
@ -226,6 +225,8 @@ class PDFViewer {
|
|||||||
|
|
||||||
#scaleTimeoutId = null;
|
#scaleTimeoutId = null;
|
||||||
|
|
||||||
|
#textLayerMode = TextLayerMode.ENABLE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {PDFViewerOptions} options
|
* @param {PDFViewerOptions} options
|
||||||
*/
|
*/
|
||||||
@ -259,7 +260,7 @@ class PDFViewer {
|
|||||||
this.downloadManager = options.downloadManager || null;
|
this.downloadManager = options.downloadManager || null;
|
||||||
this.findController = options.findController || null;
|
this.findController = options.findController || null;
|
||||||
this._scriptingManager = options.scriptingManager || null;
|
this._scriptingManager = options.scriptingManager || null;
|
||||||
this.textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
|
this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
|
||||||
this.#annotationMode =
|
this.#annotationMode =
|
||||||
options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
|
options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
|
||||||
this.#annotationEditorMode =
|
this.#annotationEditorMode =
|
||||||
@ -565,15 +566,6 @@ class PDFViewer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#createHiddenCopyElement() {
|
|
||||||
if (this.#hiddenCopyElement) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const element = (this.#hiddenCopyElement = document.createElement("div"));
|
|
||||||
element.id = "hiddenCopyElement";
|
|
||||||
this.viewer.before(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently only *some* permissions are supported.
|
* Currently only *some* permissions are supported.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
@ -582,17 +574,17 @@ class PDFViewer {
|
|||||||
const params = {
|
const params = {
|
||||||
annotationEditorMode: this.#annotationEditorMode,
|
annotationEditorMode: this.#annotationEditorMode,
|
||||||
annotationMode: this.#annotationMode,
|
annotationMode: this.#annotationMode,
|
||||||
textLayerMode: this.textLayerMode,
|
textLayerMode: this.#textLayerMode,
|
||||||
};
|
};
|
||||||
if (!permissions) {
|
if (!permissions) {
|
||||||
this.#createHiddenCopyElement();
|
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!permissions.includes(PermissionFlag.COPY)) {
|
if (
|
||||||
this.viewer.classList.add(ENABLE_PERMISSIONS_CLASS);
|
!permissions.includes(PermissionFlag.COPY) &&
|
||||||
} else {
|
this.#textLayerMode === TextLayerMode.ENABLE
|
||||||
this.#createHiddenCopyElement();
|
) {
|
||||||
|
params.textLayerMode = TextLayerMode.ENABLE_PERMISSIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!permissions.includes(PermissionFlag.MODIFY_CONTENTS)) {
|
if (!permissions.includes(PermissionFlag.MODIFY_CONTENTS)) {
|
||||||
@ -683,7 +675,7 @@ class PDFViewer {
|
|||||||
return texts.join("\n");
|
return texts.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#copyCallback(event) {
|
#copyCallback(textLayerMode, event) {
|
||||||
const selection = document.getSelection();
|
const selection = document.getSelection();
|
||||||
const { focusNode, anchorNode } = selection;
|
const { focusNode, anchorNode } = selection;
|
||||||
if (
|
if (
|
||||||
@ -699,6 +691,11 @@ class PDFViewer {
|
|||||||
// including this element so having it in the selection means that all
|
// including this element so having it in the selection means that all
|
||||||
// has been selected.
|
// has been selected.
|
||||||
|
|
||||||
|
if (textLayerMode === TextLayerMode.ENABLE_PERMISSIONS) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
// TODO: if all the pages are rendered we don't need to wait for
|
// TODO: if all the pages are rendered we don't need to wait for
|
||||||
// getAllText and we could just get text from the Selection object.
|
// getAllText and we could just get text from the Selection object.
|
||||||
|
|
||||||
@ -831,6 +828,13 @@ class PDFViewer {
|
|||||||
const { annotationEditorMode, annotationMode, textLayerMode } =
|
const { annotationEditorMode, annotationMode, textLayerMode } =
|
||||||
this.#initializePermissions(permissions);
|
this.#initializePermissions(permissions);
|
||||||
|
|
||||||
|
if (textLayerMode !== TextLayerMode.DISABLE) {
|
||||||
|
const element = (this.#hiddenCopyElement =
|
||||||
|
document.createElement("div"));
|
||||||
|
element.id = "hiddenCopyElement";
|
||||||
|
this.viewer.before(element);
|
||||||
|
}
|
||||||
|
|
||||||
if (annotationEditorMode !== AnnotationEditorType.DISABLE) {
|
if (annotationEditorMode !== AnnotationEditorType.DISABLE) {
|
||||||
const mode = annotationEditorMode;
|
const mode = annotationEditorMode;
|
||||||
|
|
||||||
@ -906,6 +910,10 @@ class PDFViewer {
|
|||||||
this._scriptingManager?.setDocument(pdfDocument); // Enable scripting.
|
this._scriptingManager?.setDocument(pdfDocument); // Enable scripting.
|
||||||
|
|
||||||
if (this.#hiddenCopyElement) {
|
if (this.#hiddenCopyElement) {
|
||||||
|
this.#copyCallbackBound = this.#copyCallback.bind(
|
||||||
|
this,
|
||||||
|
textLayerMode
|
||||||
|
);
|
||||||
document.addEventListener("copy", this.#copyCallbackBound);
|
document.addEventListener("copy", this.#copyCallbackBound);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1051,11 +1059,10 @@ class PDFViewer {
|
|||||||
this._updateScrollMode();
|
this._updateScrollMode();
|
||||||
|
|
||||||
this.viewer.removeAttribute("lang");
|
this.viewer.removeAttribute("lang");
|
||||||
// Reset all PDF document permissions.
|
|
||||||
this.viewer.classList.remove(ENABLE_PERMISSIONS_CLASS);
|
|
||||||
|
|
||||||
if (this.#hiddenCopyElement) {
|
if (this.#hiddenCopyElement) {
|
||||||
document.removeEventListener("copy", this.#copyCallbackBound);
|
document.removeEventListener("copy", this.#copyCallbackBound);
|
||||||
|
this.#copyCallbackBound = null;
|
||||||
|
|
||||||
this.#hiddenCopyElement.remove();
|
this.#hiddenCopyElement.remove();
|
||||||
this.#hiddenCopyElement = null;
|
this.#hiddenCopyElement = null;
|
||||||
|
@ -38,6 +38,8 @@ import { removeNullCharacters } from "./ui_utils.js";
|
|||||||
* contain text that matches the PDF text they are overlaying.
|
* contain text that matches the PDF text they are overlaying.
|
||||||
*/
|
*/
|
||||||
class TextLayerBuilder {
|
class TextLayerBuilder {
|
||||||
|
#enablePermissions = false;
|
||||||
|
|
||||||
#rotation = 0;
|
#rotation = 0;
|
||||||
|
|
||||||
#scale = 0;
|
#scale = 0;
|
||||||
@ -48,6 +50,7 @@ class TextLayerBuilder {
|
|||||||
highlighter = null,
|
highlighter = null,
|
||||||
accessibilityManager = null,
|
accessibilityManager = null,
|
||||||
isOffscreenCanvasSupported = true,
|
isOffscreenCanvasSupported = true,
|
||||||
|
enablePermissions = false,
|
||||||
}) {
|
}) {
|
||||||
this.textContentItemsStr = [];
|
this.textContentItemsStr = [];
|
||||||
this.renderingDone = false;
|
this.renderingDone = false;
|
||||||
@ -57,6 +60,7 @@ class TextLayerBuilder {
|
|||||||
this.highlighter = highlighter;
|
this.highlighter = highlighter;
|
||||||
this.accessibilityManager = accessibilityManager;
|
this.accessibilityManager = accessibilityManager;
|
||||||
this.isOffscreenCanvasSupported = isOffscreenCanvasSupported;
|
this.isOffscreenCanvasSupported = isOffscreenCanvasSupported;
|
||||||
|
this.#enablePermissions = enablePermissions === true;
|
||||||
|
|
||||||
this.div = document.createElement("div");
|
this.div = document.createElement("div");
|
||||||
this.div.className = "textLayer";
|
this.div.className = "textLayer";
|
||||||
@ -215,11 +219,13 @@ class TextLayerBuilder {
|
|||||||
});
|
});
|
||||||
|
|
||||||
div.addEventListener("copy", event => {
|
div.addEventListener("copy", event => {
|
||||||
|
if (!this.#enablePermissions) {
|
||||||
const selection = document.getSelection();
|
const selection = document.getSelection();
|
||||||
event.clipboardData.setData(
|
event.clipboardData.setData(
|
||||||
"text/plain",
|
"text/plain",
|
||||||
removeNullCharacters(normalizeUnicode(selection.toString()))
|
removeNullCharacters(normalizeUnicode(selection.toString()))
|
||||||
);
|
);
|
||||||
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
});
|
});
|
||||||
|
@ -49,6 +49,7 @@ const SidebarView = {
|
|||||||
const TextLayerMode = {
|
const TextLayerMode = {
|
||||||
DISABLE: 0,
|
DISABLE: 0,
|
||||||
ENABLE: 1,
|
ENABLE: 1,
|
||||||
|
ENABLE_PERMISSIONS: 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ScrollMode = {
|
const ScrollMode = {
|
||||||
|
Loading…
Reference in New Issue
Block a user