Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[editor] Support disabling of editing when pdfjs.enablePermissions is set (issue 15049) #15075

Merged
merged 1 commit into from
Jun 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions web/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,7 @@ const PDFViewerApplication = {

const container = appConfig.mainContainer,
viewer = appConfig.viewerContainer;
const annotationEditorEnabled = AppOptions.get("annotationEditorEnabled");
const pageColors = {
background: AppOptions.get("pageColorsBackground"),
foreground: AppOptions.get("pageColorsForeground"),
Expand All @@ -529,7 +530,7 @@ const PDFViewerApplication = {
l10n: this.l10n,
textLayerMode: AppOptions.get("textLayerMode"),
annotationMode: AppOptions.get("annotationMode"),
annotationEditorEnabled: AppOptions.get("annotationEditorEnabled"),
annotationEditorEnabled,
imageResourcesPath: AppOptions.get("imageResourcesPath"),
enablePrintAutoRotate: AppOptions.get("enablePrintAutoRotate"),
useOnlyCssZoom: AppOptions.get("useOnlyCssZoom"),
Expand Down Expand Up @@ -565,6 +566,15 @@ const PDFViewerApplication = {
this.findBar = new PDFFindBar(appConfig.findBar, eventBus, this.l10n);
}

if (annotationEditorEnabled) {
for (const element of [
document.getElementById("editorModeButtons"),
document.getElementById("editorModeSeparator"),
]) {
element.classList.remove("hidden");
}
}

this.pdfDocumentProperties = new PDFDocumentProperties(
appConfig.documentProperties,
this.overlayManager,
Expand Down Expand Up @@ -1196,11 +1206,6 @@ const PDFViewerApplication = {
this.toolbar.setPagesCount(pdfDocument.numPages, false);
this.secondaryToolbar.setPagesCount(pdfDocument.numPages);

if (pdfDocument.isPureXfa) {
console.warn("Warning: XFA-editing is not implemented.");
this.toolbar.updateEditorModeButtonsState(/* disabled = */ true);
}

let baseDocumentUrl;
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
baseDocumentUrl = null;
Expand Down Expand Up @@ -2242,10 +2247,6 @@ function webViewerInitialized() {
appConfig.toolbar.viewFind.classList.add("hidden");
}

if (PDFViewerApplication.pdfViewer.enableAnnotationEditor) {
appConfig.toolbar.editorModeButtons.classList.remove("hidden");
}

appConfig.mainContainer.addEventListener(
"transitionend",
function (evt) {
Expand Down
4 changes: 3 additions & 1 deletion web/app_options.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ const OptionKind = {
const defaultOptions = {
annotationEditorEnabled: {
/** @type {boolean} */
value: typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING"),
value:
typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING"),
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
},
annotationMode: {
Expand Down
86 changes: 53 additions & 33 deletions web/base_viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,6 @@ class BaseViewer {

#annotationMode = AnnotationMode.ENABLE_FORMS;

#previousAnnotationMode = null;

#enablePermissions = false;

#previousContainerHeight = 0;
Expand Down Expand Up @@ -275,6 +273,9 @@ class BaseViewer {
this.textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
this.#annotationMode =
options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
this.#annotationEditorMode = options.annotationEditorEnabled
? AnnotationEditorType.NONE
: null;
this.imageResourcesPath = options.imageResourcesPath || "";
this.enablePrintAutoRotate = options.enablePrintAutoRotate || false;
this.renderer = options.renderer || RendererType.CANVAS;
Expand All @@ -284,10 +285,6 @@ class BaseViewer {
this.#enablePermissions = options.enablePermissions || false;
this.pageColors = options.pageColors || null;

if (options.annotationEditorEnabled === true) {
this.#annotationEditorUIManager = new AnnotationEditorUIManager();
}

if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) {
if (
this.pageColors &&
Expand Down Expand Up @@ -354,13 +351,6 @@ class BaseViewer {
return this.#annotationMode === AnnotationMode.ENABLE_FORMS;
}

/**
* @type {boolean}
*/
get enableAnnotationEditor() {
return !!this.#annotationEditorUIManager;
}

/**
* @type {boolean}
*/
Expand Down Expand Up @@ -553,25 +543,35 @@ class BaseViewer {

/**
* Currently only *some* permissions are supported.
* @returns {Object}
*/
#initializePermissions(permissions) {
const params = {
annotationEditorMode: this.#annotationEditorMode,
annotationMode: this.#annotationMode,
textLayerMode: this.textLayerMode,
};
if (!permissions) {
return;
return params;
}

if (!permissions.includes(PermissionFlag.COPY)) {
this.viewer.classList.add(ENABLE_PERMISSIONS_CLASS);
}

if (!permissions.includes(PermissionFlag.MODIFY_CONTENTS)) {
params.annotationEditorMode = null;
}

if (
!permissions.includes(PermissionFlag.MODIFY_ANNOTATIONS) &&
!permissions.includes(PermissionFlag.FILL_INTERACTIVE_FORMS)
!permissions.includes(PermissionFlag.FILL_INTERACTIVE_FORMS) &&
this.#annotationMode === AnnotationMode.ENABLE_FORMS
) {
if (this.#annotationMode === AnnotationMode.ENABLE_FORMS) {
this.#previousAnnotationMode = this.#annotationMode; // Allow resetting.
this.#annotationMode = AnnotationMode.ENABLE;
}
params.annotationMode = AnnotationMode.ENABLE;
}

return params;
}

#onePageRenderedOrForceFetch() {
Expand Down Expand Up @@ -706,7 +706,23 @@ class BaseViewer {
}
this._firstPageCapability.resolve(firstPdfPage);
this._optionalContentConfigPromise = optionalContentConfigPromise;
this.#initializePermissions(permissions);

const { annotationEditorMode, annotationMode, textLayerMode } =
this.#initializePermissions(permissions);

if (annotationEditorMode !== null) {
if (isPureXfa) {
console.warn("Warning: XFA-editing is not implemented.");
} else {
// Ensure that the Editor buttons, in the toolbar, are updated.
this.eventBus.dispatch("annotationeditormodechanged", {
source: this,
mode: annotationEditorMode,
});

this.#annotationEditorUIManager = new AnnotationEditorUIManager();
}
}

const viewerElement =
this._scrollMode === ScrollMode.PAGE ? null : this.viewer;
Expand All @@ -715,14 +731,13 @@ class BaseViewer {
scale: scale * PixelsPerInch.PDF_TO_CSS_UNITS,
});
const textLayerFactory =
this.textLayerMode !== TextLayerMode.DISABLE && !isPureXfa
? this
: null;
textLayerMode !== TextLayerMode.DISABLE && !isPureXfa ? this : null;
const annotationLayerFactory =
this.#annotationMode !== AnnotationMode.DISABLE ? this : null;
annotationMode !== AnnotationMode.DISABLE ? this : null;
const xfaLayerFactory = isPureXfa ? this : null;
const annotationEditorLayerFactory =
this.#annotationEditorUIManager && !isPureXfa ? this : null;
const annotationEditorLayerFactory = this.#annotationEditorUIManager
? this
: null;

for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
const pageView = new PDFPageView({
Expand All @@ -734,9 +749,9 @@ class BaseViewer {
optionalContentConfigPromise,
renderingQueue: this.renderingQueue,
textLayerFactory,
textLayerMode: this.textLayerMode,
textLayerMode,
annotationLayerFactory,
annotationMode: this.#annotationMode,
annotationMode,
xfaLayerFactory,
annotationEditorLayerFactory,
textHighlighterFactory: this,
Expand Down Expand Up @@ -868,6 +883,10 @@ class BaseViewer {
}

_resetView() {
if (this.#annotationEditorMode !== null) {
this.#annotationEditorMode = AnnotationEditorType.NONE;
}
this.#annotationEditorUIManager = null;
this._pages = [];
this._currentPageNumber = 1;
this._currentScale = UNKNOWN_SCALE;
Expand Down Expand Up @@ -913,11 +932,6 @@ class BaseViewer {
this.viewer.removeAttribute("lang");
// Reset all PDF document permissions.
this.viewer.classList.remove(ENABLE_PERMISSIONS_CLASS);

if (this.#previousAnnotationMode !== null) {
this.#annotationMode = this.#previousAnnotationMode;
this.#previousAnnotationMode = null;
}
}

#ensurePageViewVisible() {
Expand Down Expand Up @@ -2125,6 +2139,9 @@ class BaseViewer {
}
}

/**
* @type {number | null}
*/
get annotationEditorMode() {
return this.#annotationEditorMode;
}
Expand All @@ -2142,6 +2159,9 @@ class BaseViewer {
if (!isValidAnnotationEditorMode(mode)) {
throw new Error(`Invalid AnnotationEditor mode: ${mode}`);
}
if (!this.pdfDocument) {
return;
}
this.#annotationEditorMode = mode;
this.eventBus.dispatch("annotationeditormodechanged", {
source: this,
Expand Down
26 changes: 15 additions & 11 deletions web/toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ class Toolbar {
this.pageScale = DEFAULT_SCALE;
this._updateUIState(true);
this.updateLoadingIndicatorState();
this.updateEditorModeButtonsState();

// Reset the Editor buttons too, since they're document specific.
this.eventBus.dispatch("toolbarreset", { source: this });
}

_bindListeners(options) {
Expand Down Expand Up @@ -212,7 +214,7 @@ class Toolbar {
editorFreeTextButton,
editorInkButton,
}) {
this.eventBus._on("annotationeditormodechanged", evt => {
const editorModeChanged = (evt, disableButtons = false) => {
const editorButtons = [
[AnnotationEditorType.NONE, editorNoneButton],
[AnnotationEditorType.FREETEXT, editorFreeTextButton],
Expand All @@ -223,6 +225,17 @@ class Toolbar {
const checked = mode === evt.mode;
button.classList.toggle("toggled", checked);
button.setAttribute("aria-checked", checked);
button.disabled = disableButtons;
}
};
this.eventBus._on("annotationeditormodechanged", editorModeChanged);

this.eventBus._on("toolbarreset", evt => {
if (evt.source === this) {
editorModeChanged(
{ mode: AnnotationEditorType.NONE },
/* disableButtons = */ true
);
}
});
}
Expand Down Expand Up @@ -286,15 +299,6 @@ class Toolbar {
pageNumber.classList.toggle(PAGE_NUMBER_LOADING_INDICATOR, loading);
}

updateEditorModeButtonsState(disabled = false) {
const { editorNoneButton, editorFreeTextButton, editorInkButton } =
this.items;

editorNoneButton.disabled = disabled;
editorFreeTextButton.disabled = disabled;
editorInkButton.disabled = disabled;
}

/**
* Increase the width of the zoom dropdown DOM element if, and only if, it's
* too narrow to fit the *longest* of the localized strings.
Expand Down
37 changes: 20 additions & 17 deletions web/viewer.html
Original file line number Diff line number Diff line change
Expand Up @@ -263,41 +263,44 @@
<span id="numPages" class="toolbarLabel"></span>
</div>
<div id="toolbarViewerRight">
<div id="editorModeButtons" class="splitToolbarButton toggled hidden" role="radiogroup">
<button id="editorNone" class="toolbarButton toggled" title="Disable Annotation Editing" role="radio" aria-checked="true" tabindex="31" data-l10n-id="editor_none">
<span data-l10n-id="editor_none_label">Disable Editing</span>
</button>
<button id="editorFreeText" class="toolbarButton" title="Add FreeText Annotation" role="radio" aria-checked="false" tabindex="32" data-l10n-id="editor_free_text">
<span data-l10n-id="editor_free_text_label">FreeText Annotation</span>
</button>
<button id="editorInk" class="toolbarButton" title="Add Ink Annotation" role="radio" aria-checked="false" tabindex="33" data-l10n-id="editor_ink">
<span data-l10n-id="editor_ink_label">Ink Annotation</span>
</button>
</div>

<button id="presentationMode" class="toolbarButton hiddenLargeView" title="Switch to Presentation Mode" tabindex="43" data-l10n-id="presentation_mode">
<button id="presentationMode" class="toolbarButton hiddenLargeView" title="Switch to Presentation Mode" tabindex="31" data-l10n-id="presentation_mode">
<span data-l10n-id="presentation_mode_label">Presentation Mode</span>
</button>

<!--#if GENERIC-->
<button id="openFile" class="toolbarButton hiddenLargeView" title="Open File" tabindex="44" data-l10n-id="open_file">
<button id="openFile" class="toolbarButton hiddenLargeView" title="Open File" tabindex="32" data-l10n-id="open_file">
<span data-l10n-id="open_file_label">Open</span>
</button>
<!--#endif-->

<button id="print" class="toolbarButton hiddenMediumView" title="Print" tabindex="45" data-l10n-id="print">
<button id="print" class="toolbarButton hiddenMediumView" title="Print" tabindex="33" data-l10n-id="print">
<span data-l10n-id="print_label">Print</span>
</button>

<button id="download" class="toolbarButton hiddenMediumView" title="Download" tabindex="46" data-l10n-id="download">
<button id="download" class="toolbarButton hiddenMediumView" title="Download" tabindex="34" data-l10n-id="download">
<span data-l10n-id="download_label">Download</span>
</button>
<a href="#" id="viewBookmark" class="toolbarButton hiddenSmallView" title="Current view (copy or open in new window)" tabindex="47" data-l10n-id="bookmark">
<a href="#" id="viewBookmark" class="toolbarButton hiddenSmallView" title="Current view (copy or open in new window)" tabindex="35" data-l10n-id="bookmark">
<span data-l10n-id="bookmark_label">Current View</span>
</a>

<div class="verticalToolbarSeparator hiddenSmallView"></div>

<div id="editorModeButtons" class="splitToolbarButton toggled hidden" role="radiogroup">
<button id="editorNone" class="toolbarButton toggled" disabled="disabled" title="Disable Annotation Editing" role="radio" aria-checked="true" tabindex="36" data-l10n-id="editor_none">
<span data-l10n-id="editor_none_label">Disable Editing</span>
</button>
<button id="editorFreeText" class="toolbarButton" disabled="disabled" title="Add FreeText Annotation" role="radio" aria-checked="false" tabindex="37" data-l10n-id="editor_free_text">
<span data-l10n-id="editor_free_text_label">FreeText Annotation</span>
</button>
<button id="editorInk" class="toolbarButton" disabled="disabled" title="Add Ink Annotation" role="radio" aria-checked="false" tabindex="38" data-l10n-id="editor_ink">
<span data-l10n-id="editor_ink_label">Ink Annotation</span>
</button>
</div>

Snuffleupagus marked this conversation as resolved.
Show resolved Hide resolved
<!-- Should be visible when the "editorModeButtons" are visible. -->
<div id="editorModeSeparator" class="verticalToolbarSeparator hidden"></div>

<button id="secondaryToolbarToggle" class="toolbarButton" title="Tools" tabindex="48" data-l10n-id="tools" aria-expanded="false" aria-controls="secondaryToolbar">
<span data-l10n-id="tools_label">Tools</span>
</button>
Expand Down
1 change: 0 additions & 1 deletion web/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ function getViewerConfiguration() {
? document.getElementById("openFile")
: null,
print: document.getElementById("print"),
editorModeButtons: document.getElementById("editorModeButtons"),
editorNoneButton: document.getElementById("editorNone"),
editorFreeTextButton: document.getElementById("editorFreeText"),
editorInkButton: document.getElementById("editorInk"),
Expand Down