2017-07-14 21:24:32 +09:00
|
|
|
/* Copyright 2017 Mozilla Foundation
|
2013-07-19 00:18:27 +09:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2021-12-15 21:54:29 +09:00
|
|
|
/** @typedef {import("./event_utils").EventBus} EventBus */
|
2021-12-15 07:59:17 +09:00
|
|
|
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
|
|
|
|
|
2022-04-05 20:56:51 +09:00
|
|
|
import { isValidRotation, parseQueryString } from "./ui_utils.js";
|
2021-12-16 01:09:16 +09:00
|
|
|
import { waitOnEventOrTimeout } from "./event_utils.js";
|
2017-03-28 08:07:27 +09:00
|
|
|
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
// Heuristic value used when force-resetting `this._blockHashChange`.
|
|
|
|
const HASH_CHANGE_TIMEOUT = 1000; // milliseconds
|
2017-08-11 20:54:30 +09:00
|
|
|
// Heuristic value used when adding the current position to the browser history.
|
|
|
|
const POSITION_UPDATED_THRESHOLD = 50;
|
2017-07-20 22:57:26 +09:00
|
|
|
// Heuristic value used when adding a temporary position to the browser history.
|
Reduce the value of `UPDATE_VIEWAREA_TIMEOUT` and simplify the 'popstate' event handler to avoid subtle bugs
When testing the new `PDFHistory` implementation in practice, I felt that the current value of `UPDATE_VIEWAREA_TIMEOUT` is too large to be truly useful.
The purpose of the timeout is to attempt to address (the PDF.js part of) https://bugzilla.mozilla.org/show_bug.cgi?id=1153393, and it's currently fairly easy for the user e.g. close the browser before the timeout had a change to finish.
Obviously, the timeout is a best-effort solution, but with the current value of `UPDATE_VIEWAREA_TIMEOUT` it's not as useful as one would want.
Please note that lowering it shouldn't be a problem, since it still prevents the browser history from updating at *every* 'updateviewarea' event or during (quick) scrolling, which is all that's really needed to not impact the UX negatively.
---
Furthermore, with this lower timeout, we can also simplify the part of the 'popstate' event handler that attempted to update the browser history with the current position before moving back. In most cases, the current position will now already exist in the history, and this *greatly* decreases the complexity of this code path.
The main impetus for this change though, is that I unfortunately found that given the asynchronous nature of updating the browser history, there is some *edge* cases where that code could cause history corruption.
In practice, the user could thus get "stuck" at a particular history entry and not be able to move back. I haven't got any reliable STR for this, since it's so difficult to trigger, but it involved navigating around in a document such that a number of destinations are added to the browser history and then changing the rotation before going back/forward in the history.
Rather that attempting to patch this code, and making it even more difficult to understand than it already is or adding more asynchronous behaviour, by far the easiest solution is to remove it and simply rely on the (lowered) `UPDATE_VIEWAREA_TIMEOUT` instead.
2017-09-07 19:19:59 +09:00
|
|
|
const UPDATE_VIEWAREA_TIMEOUT = 1000; // milliseconds
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @typedef {Object} PDFHistoryOptions
|
|
|
|
* @property {IPDFLinkService} linkService - The navigation/linking service.
|
|
|
|
* @property {EventBus} eventBus - The application event bus.
|
|
|
|
*/
|
|
|
|
|
Add support for updating the document hash, off by default, when the browser history is updated (issue 5753)
This is *really* the best that we can do here, since other proposed solutions would interfere with (and break) the painstakingly implemented browsing history that's present in the default viewer.
I'm still not convinced that this is a good idea in general, but this patch implements it in a way where it is possible to toggle[1] for users that wish to have this feature. In particular, there's a couple of reasons why I'm not finding this feature necessary/great:
- It's already possible to easily obtain the current hash, by simply clicking on the `viewBookmark` button at any time.
- Hash changes requires a bit of special handling[2], i.e. extra code, to prevent issues when the browser history is traversed (see `PDFHistory._popState`). Currently this is only necessary when the user has manually changed the hash, with this patch it will always be the case (assuming the feature is active).
- It's not always possible to change the URL when updating the browser history. For example: In the Firefox built-in viewer, the URL cannot be modified for local files (i.e. those using the `file://` protocol).
This leads to inconsistent behaviour, and may in some cases even result in errors being thrown and the history thus not updating, if the browser prevents changes to the URL during `pushState`/`replaceState` calls.
---
[1] Using the `historyUpdateUrl` viewer preference.
[2] This depends, to a great extent, on browsers always firing `popstate` events *before* `hashchange` events, which may or may not actually be guaranteed.
2019-01-03 23:45:33 +09:00
|
|
|
/**
|
|
|
|
* @typedef {Object} InitializeParameters
|
|
|
|
* @property {string} fingerprint - The PDF document's unique fingerprint.
|
2019-10-12 23:30:32 +09:00
|
|
|
* @property {boolean} [resetHistory] - Reset the browsing history.
|
|
|
|
* @property {boolean} [updateUrl] - Attempt to update the document URL, with
|
|
|
|
* the current hash, when pushing/replacing browser history entries.
|
Add support for updating the document hash, off by default, when the browser history is updated (issue 5753)
This is *really* the best that we can do here, since other proposed solutions would interfere with (and break) the painstakingly implemented browsing history that's present in the default viewer.
I'm still not convinced that this is a good idea in general, but this patch implements it in a way where it is possible to toggle[1] for users that wish to have this feature. In particular, there's a couple of reasons why I'm not finding this feature necessary/great:
- It's already possible to easily obtain the current hash, by simply clicking on the `viewBookmark` button at any time.
- Hash changes requires a bit of special handling[2], i.e. extra code, to prevent issues when the browser history is traversed (see `PDFHistory._popState`). Currently this is only necessary when the user has manually changed the hash, with this patch it will always be the case (assuming the feature is active).
- It's not always possible to change the URL when updating the browser history. For example: In the Firefox built-in viewer, the URL cannot be modified for local files (i.e. those using the `file://` protocol).
This leads to inconsistent behaviour, and may in some cases even result in errors being thrown and the history thus not updating, if the browser prevents changes to the URL during `pushState`/`replaceState` calls.
---
[1] Using the `historyUpdateUrl` viewer preference.
[2] This depends, to a great extent, on browsers always firing `popstate` events *before* `hashchange` events, which may or may not actually be guaranteed.
2019-01-03 23:45:33 +09:00
|
|
|
*/
|
|
|
|
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
/**
|
|
|
|
* @typedef {Object} PushParameters
|
2019-10-12 23:30:32 +09:00
|
|
|
* @property {string} [namedDest] - The named destination. If absent, a
|
|
|
|
* stringified version of `explicitDest` is used.
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
* @property {Array} explicitDest - The explicit destination array.
|
|
|
|
* @property {number} pageNumber - The page to which the destination points.
|
|
|
|
*/
|
|
|
|
|
|
|
|
function getCurrentHash() {
|
|
|
|
return document.location.hash;
|
|
|
|
}
|
|
|
|
|
2017-07-14 21:24:32 +09:00
|
|
|
class PDFHistory {
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
/**
|
|
|
|
* @param {PDFHistoryOptions} options
|
|
|
|
*/
|
2017-07-14 21:24:32 +09:00
|
|
|
constructor({ linkService, eventBus }) {
|
|
|
|
this.linkService = linkService;
|
2020-02-27 23:02:03 +09:00
|
|
|
this.eventBus = eventBus;
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
|
2019-12-03 20:04:49 +09:00
|
|
|
this._initialized = false;
|
|
|
|
this._fingerprint = "";
|
|
|
|
this.reset();
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
|
2019-12-03 20:04:49 +09:00
|
|
|
this._boundEvents = null;
|
2022-04-05 20:56:51 +09:00
|
|
|
// Ensure that we don't miss a "pagesinit" event,
|
|
|
|
// by registering the listener immediately.
|
Re-factor the `EventBus` to allow servicing of "external" event listeners *after* the viewer components have updated
Since the goal has always been, essentially since the `EventBus` abstraction was added, to remove all dispatching of DOM events[1] from the viewer components this patch tries to address one thing that came up when updating the examples:
The DOM events are always dispatched last, and it's thus guaranteed that all internal event listeners have been invoked first.
However, there's no such guarantees with the general `EventBus` functionality and the order in which event listeners are invoked is *not* specified. With the promotion of the `EventBus` in the examples, over DOM events, it seems like a good idea to at least *try* to keep this ordering invariant[2] intact.
Obviously this won't prevent anyone from manually calling the new *internal* viewer component methods on the `EventBus`, but hopefully that won't be too common since any existing third-party code would obviously use the `on`/`off` methods and that all of the examples shows the *correct* usage (which should be similarily documented on the "Third party viewer usage" Wiki-page).
---
[1] Looking at the various Firefox-tests, I'm not sure that it'll be possible to (easily) re-write all of them to not rely on DOM events (since getting access to `PDFViewerApplication` might be generally difficult/messy depending on scopes).
In any case, even if technically feasible, it would most likely add *a lot* of complication that may not be desireable in the various Firefox-tests. All-in-all, I'd be fine with keeping the DOM events only for the `MOZCENTRAL` target and gated on `Cu.isInAutomation` (or similar) rather than a preference.
[2] I wouldn't expect any *real* bugs in a custom implementation, simply based on event ordering, but it nonetheless seem like a good idea if any "external" events are still handled last.
2020-02-27 07:33:27 +09:00
|
|
|
this.eventBus._on("pagesinit", () => {
|
2019-12-03 20:04:49 +09:00
|
|
|
this._isPagesLoaded = false;
|
|
|
|
|
2020-12-30 00:36:58 +09:00
|
|
|
this.eventBus._on(
|
|
|
|
"pagesloaded",
|
|
|
|
evt => {
|
|
|
|
this._isPagesLoaded = !!evt.pagesCount;
|
|
|
|
},
|
|
|
|
{ once: true }
|
|
|
|
);
|
2017-08-11 20:54:30 +09:00
|
|
|
});
|
2017-07-14 21:24:32 +09:00
|
|
|
}
|
2017-03-28 08:07:27 +09:00
|
|
|
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
/**
|
|
|
|
* Initialize the history for the PDF document, using either the current
|
|
|
|
* browser history entry or the document hash, whichever is present.
|
Add support for updating the document hash, off by default, when the browser history is updated (issue 5753)
This is *really* the best that we can do here, since other proposed solutions would interfere with (and break) the painstakingly implemented browsing history that's present in the default viewer.
I'm still not convinced that this is a good idea in general, but this patch implements it in a way where it is possible to toggle[1] for users that wish to have this feature. In particular, there's a couple of reasons why I'm not finding this feature necessary/great:
- It's already possible to easily obtain the current hash, by simply clicking on the `viewBookmark` button at any time.
- Hash changes requires a bit of special handling[2], i.e. extra code, to prevent issues when the browser history is traversed (see `PDFHistory._popState`). Currently this is only necessary when the user has manually changed the hash, with this patch it will always be the case (assuming the feature is active).
- It's not always possible to change the URL when updating the browser history. For example: In the Firefox built-in viewer, the URL cannot be modified for local files (i.e. those using the `file://` protocol).
This leads to inconsistent behaviour, and may in some cases even result in errors being thrown and the history thus not updating, if the browser prevents changes to the URL during `pushState`/`replaceState` calls.
---
[1] Using the `historyUpdateUrl` viewer preference.
[2] This depends, to a great extent, on browsers always firing `popstate` events *before* `hashchange` events, which may or may not actually be guaranteed.
2019-01-03 23:45:33 +09:00
|
|
|
* @param {InitializeParameters} params
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
*/
|
Add support for updating the document hash, off by default, when the browser history is updated (issue 5753)
This is *really* the best that we can do here, since other proposed solutions would interfere with (and break) the painstakingly implemented browsing history that's present in the default viewer.
I'm still not convinced that this is a good idea in general, but this patch implements it in a way where it is possible to toggle[1] for users that wish to have this feature. In particular, there's a couple of reasons why I'm not finding this feature necessary/great:
- It's already possible to easily obtain the current hash, by simply clicking on the `viewBookmark` button at any time.
- Hash changes requires a bit of special handling[2], i.e. extra code, to prevent issues when the browser history is traversed (see `PDFHistory._popState`). Currently this is only necessary when the user has manually changed the hash, with this patch it will always be the case (assuming the feature is active).
- It's not always possible to change the URL when updating the browser history. For example: In the Firefox built-in viewer, the URL cannot be modified for local files (i.e. those using the `file://` protocol).
This leads to inconsistent behaviour, and may in some cases even result in errors being thrown and the history thus not updating, if the browser prevents changes to the URL during `pushState`/`replaceState` calls.
---
[1] Using the `historyUpdateUrl` viewer preference.
[2] This depends, to a great extent, on browsers always firing `popstate` events *before* `hashchange` events, which may or may not actually be guaranteed.
2019-01-03 23:45:33 +09:00
|
|
|
initialize({ fingerprint, resetHistory = false, updateUrl = false }) {
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
if (!fingerprint || typeof fingerprint !== "string") {
|
|
|
|
console.error(
|
|
|
|
'PDFHistory.initialize: The "fingerprint" must be a non-empty string.'
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
2019-12-03 20:04:49 +09:00
|
|
|
// Ensure that any old state is always reset upon initialization.
|
|
|
|
if (this._initialized) {
|
|
|
|
this.reset();
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
}
|
2019-12-03 20:04:49 +09:00
|
|
|
const reInitialized =
|
|
|
|
this._fingerprint !== "" && this._fingerprint !== fingerprint;
|
|
|
|
this._fingerprint = fingerprint;
|
|
|
|
this._updateUrl = updateUrl === true;
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
|
2019-12-03 20:04:49 +09:00
|
|
|
this._initialized = true;
|
|
|
|
this._bindEvents();
|
|
|
|
const state = window.history.state;
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
|
|
|
|
this._popStateInProgress = false;
|
|
|
|
this._blockHashChange = 0;
|
|
|
|
this._currentHash = getCurrentHash();
|
2017-08-11 20:54:30 +09:00
|
|
|
this._numPositionUpdates = 0;
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
|
2017-10-05 20:56:40 +09:00
|
|
|
this._uid = this._maxUid = 0;
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
this._destination = null;
|
|
|
|
this._position = null;
|
|
|
|
|
2019-01-07 00:39:43 +09:00
|
|
|
if (!this._isValidState(state, /* checkReload = */ true) || resetHistory) {
|
2020-05-07 20:53:07 +09:00
|
|
|
const { hash, page, rotation } = this._parseCurrentHash(
|
|
|
|
/* checkNameddest = */ true
|
|
|
|
);
|
2017-03-28 08:07:27 +09:00
|
|
|
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
if (!hash || reInitialized || resetHistory) {
|
|
|
|
// Ensure that the browser history is reset on PDF document load.
|
|
|
|
this._pushOrReplaceState(null, /* forceReplace = */ true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Ensure that the browser history is initialized correctly when
|
|
|
|
// the document hash is present on PDF document load.
|
2017-08-21 18:56:49 +09:00
|
|
|
this._pushOrReplaceState(
|
|
|
|
{ hash, page, rotation },
|
|
|
|
/* forceReplace = */ true
|
|
|
|
);
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
return;
|
|
|
|
}
|
2017-03-28 08:07:27 +09:00
|
|
|
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
// The browser history contains a valid entry, ensure that the history is
|
|
|
|
// initialized correctly on PDF document load.
|
2019-12-27 08:22:32 +09:00
|
|
|
const destination = state.destination;
|
2017-07-20 22:57:26 +09:00
|
|
|
this._updateInternalState(
|
|
|
|
destination,
|
|
|
|
state.uid,
|
|
|
|
/* removeTemporary = */ true
|
|
|
|
);
|
2017-08-21 18:56:49 +09:00
|
|
|
|
|
|
|
if (destination.rotation !== undefined) {
|
2019-12-03 20:04:49 +09:00
|
|
|
this._initialRotation = destination.rotation;
|
2017-08-21 18:56:49 +09:00
|
|
|
}
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
if (destination.dest) {
|
2019-12-03 20:04:49 +09:00
|
|
|
this._initialBookmark = JSON.stringify(destination.dest);
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
|
|
|
|
// If the history is updated, e.g. through the user changing the hash,
|
|
|
|
// before the initial destination has become visible, then we do *not*
|
|
|
|
// want to potentially add `this._position` to the browser history.
|
|
|
|
this._destination.page = null;
|
|
|
|
} else if (destination.hash) {
|
2019-12-03 20:04:49 +09:00
|
|
|
this._initialBookmark = destination.hash;
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
} else if (destination.page) {
|
|
|
|
// Fallback case; shouldn't be necessary, but better safe than sorry.
|
2019-12-03 20:04:49 +09:00
|
|
|
this._initialBookmark = `page=${destination.page}`;
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-03 20:04:49 +09:00
|
|
|
/**
|
|
|
|
* Reset the current `PDFHistory` instance, and consequently prevent any
|
|
|
|
* further updates and/or navigation of the browser history.
|
|
|
|
*/
|
|
|
|
reset() {
|
|
|
|
if (this._initialized) {
|
|
|
|
this._pageHide(); // Simulate a 'pagehide' event when resetting.
|
|
|
|
|
|
|
|
this._initialized = false;
|
|
|
|
this._unbindEvents();
|
|
|
|
}
|
|
|
|
if (this._updateViewareaTimeout) {
|
|
|
|
clearTimeout(this._updateViewareaTimeout);
|
|
|
|
this._updateViewareaTimeout = null;
|
|
|
|
}
|
|
|
|
this._initialBookmark = null;
|
|
|
|
this._initialRotation = null;
|
|
|
|
}
|
|
|
|
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
/**
|
|
|
|
* Push an internal destination to the browser history.
|
|
|
|
* @param {PushParameters}
|
|
|
|
*/
|
2018-12-07 02:32:41 +09:00
|
|
|
push({ namedDest = null, explicitDest, pageNumber }) {
|
2019-12-03 20:04:49 +09:00
|
|
|
if (!this._initialized) {
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
return;
|
|
|
|
}
|
2018-12-07 02:32:41 +09:00
|
|
|
if (namedDest && typeof namedDest !== "string") {
|
|
|
|
console.error(
|
|
|
|
"PDFHistory.push: " +
|
|
|
|
`"${namedDest}" is not a valid namedDest parameter.`
|
|
|
|
);
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
return;
|
2018-12-07 02:32:41 +09:00
|
|
|
} else if (!Array.isArray(explicitDest)) {
|
|
|
|
console.error(
|
|
|
|
"PDFHistory.push: " +
|
|
|
|
`"${explicitDest}" is not a valid explicitDest parameter.`
|
|
|
|
);
|
|
|
|
return;
|
2021-03-24 21:55:56 +09:00
|
|
|
} else if (!this._isValidPage(pageNumber)) {
|
2018-12-07 02:32:41 +09:00
|
|
|
// Allow an unset `pageNumber` if and only if the history is still empty;
|
|
|
|
// please refer to the `this._destination.page = null;` comment above.
|
|
|
|
if (pageNumber !== null || this._destination) {
|
|
|
|
console.error(
|
|
|
|
"PDFHistory.push: " +
|
|
|
|
`"${pageNumber}" is not a valid pageNumber parameter.`
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
}
|
|
|
|
|
2019-12-27 08:22:32 +09:00
|
|
|
const hash = namedDest || JSON.stringify(explicitDest);
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
if (!hash) {
|
|
|
|
// The hash *should* never be undefined, but if that were to occur,
|
|
|
|
// avoid any possible issues by not updating the browser history.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let forceReplace = false;
|
|
|
|
if (
|
|
|
|
this._destination &&
|
2017-10-10 01:00:26 +09:00
|
|
|
(isDestHashesEqual(this._destination.hash, hash) ||
|
|
|
|
isDestArraysEqual(this._destination.dest, explicitDest))
|
|
|
|
) {
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
// When the new destination is identical to `this._destination`, and
|
|
|
|
// its `page` is undefined, replace the current browser history entry.
|
|
|
|
// NOTE: This can only occur if `this._destination` was set either:
|
|
|
|
// - through the document hash being specified on load.
|
|
|
|
// - through the user changing the hash of the document.
|
|
|
|
if (this._destination.page) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
forceReplace = true;
|
|
|
|
}
|
|
|
|
if (this._popStateInProgress && !forceReplace) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._pushOrReplaceState(
|
|
|
|
{
|
|
|
|
dest: explicitDest,
|
|
|
|
hash,
|
|
|
|
page: pageNumber,
|
2017-08-21 18:56:49 +09:00
|
|
|
rotation: this.linkService.rotation,
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
},
|
|
|
|
forceReplace
|
|
|
|
);
|
2017-09-07 19:06:43 +09:00
|
|
|
|
|
|
|
if (!this._popStateInProgress) {
|
|
|
|
// Prevent the browser history from updating while the new destination is
|
|
|
|
// being scrolled into view, to avoid potentially inconsistent state.
|
|
|
|
this._popStateInProgress = true;
|
|
|
|
// We defer the resetting of `this._popStateInProgress`, to account for
|
2021-03-24 23:18:40 +09:00
|
|
|
// e.g. zooming occurring when the new destination is being navigated to.
|
2017-09-07 19:06:43 +09:00
|
|
|
Promise.resolve().then(() => {
|
2020-10-04 01:08:30 +09:00
|
|
|
this._popStateInProgress = false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Push a page to the browser history; generally the `push` method should be
|
|
|
|
* used instead.
|
|
|
|
* @param {number} pageNumber
|
|
|
|
*/
|
|
|
|
pushPage(pageNumber) {
|
|
|
|
if (!this._initialized) {
|
|
|
|
return;
|
|
|
|
}
|
2021-03-24 21:55:56 +09:00
|
|
|
if (!this._isValidPage(pageNumber)) {
|
2020-10-04 01:08:30 +09:00
|
|
|
console.error(
|
|
|
|
`PDFHistory.pushPage: "${pageNumber}" is not a valid page number.`
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-10-31 19:24:39 +09:00
|
|
|
if (this._destination?.page === pageNumber) {
|
2020-10-04 01:08:30 +09:00
|
|
|
// When the new page is identical to the one in `this._destination`, we
|
|
|
|
// don't want to add a potential duplicate entry in the browser history.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (this._popStateInProgress) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._pushOrReplaceState({
|
2021-03-25 06:07:29 +09:00
|
|
|
// Simulate an internal destination, for `this._tryPushCurrentPosition`:
|
|
|
|
dest: null,
|
2020-10-04 01:08:30 +09:00
|
|
|
hash: `page=${pageNumber}`,
|
|
|
|
page: pageNumber,
|
|
|
|
rotation: this.linkService.rotation,
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!this._popStateInProgress) {
|
|
|
|
// Prevent the browser history from updating while the new page is
|
|
|
|
// being scrolled into view, to avoid potentially inconsistent state.
|
|
|
|
this._popStateInProgress = true;
|
|
|
|
// We defer the resetting of `this._popStateInProgress`, to account for
|
2021-03-24 23:18:40 +09:00
|
|
|
// e.g. zooming occurring when the new page is being navigated to.
|
2020-10-04 01:08:30 +09:00
|
|
|
Promise.resolve().then(() => {
|
2017-09-07 19:06:43 +09:00
|
|
|
this._popStateInProgress = false;
|
|
|
|
});
|
|
|
|
}
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Push the current position to the browser history.
|
|
|
|
*/
|
|
|
|
pushCurrentPosition() {
|
2019-12-03 20:04:49 +09:00
|
|
|
if (!this._initialized || this._popStateInProgress) {
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
this._tryPushCurrentPosition();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Go back one step in the browser history.
|
|
|
|
* NOTE: Avoids navigating away from the document, useful for "named actions".
|
|
|
|
*/
|
|
|
|
back() {
|
2019-12-03 20:04:49 +09:00
|
|
|
if (!this._initialized || this._popStateInProgress) {
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
return;
|
|
|
|
}
|
2019-12-27 08:22:32 +09:00
|
|
|
const state = window.history.state;
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
if (this._isValidState(state) && state.uid > 0) {
|
|
|
|
window.history.back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Go forward one step in the browser history.
|
|
|
|
* NOTE: Avoids navigating away from the document, useful for "named actions".
|
|
|
|
*/
|
|
|
|
forward() {
|
2019-12-03 20:04:49 +09:00
|
|
|
if (!this._initialized || this._popStateInProgress) {
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
return;
|
|
|
|
}
|
2019-12-27 08:22:32 +09:00
|
|
|
const state = window.history.state;
|
2017-10-05 20:56:40 +09:00
|
|
|
if (this._isValidState(state) && state.uid < this._maxUid) {
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
window.history.forward();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-10-13 00:02:54 +09:00
|
|
|
* @type {boolean} Indicating if the user is currently moving through the
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
* browser history, useful e.g. for skipping the next 'hashchange' event.
|
|
|
|
*/
|
|
|
|
get popStateInProgress() {
|
2019-12-03 20:04:49 +09:00
|
|
|
return (
|
|
|
|
this._initialized &&
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
(this._popStateInProgress || this._blockHashChange > 0)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-12-03 20:04:49 +09:00
|
|
|
get initialBookmark() {
|
|
|
|
return this._initialized ? this._initialBookmark : null;
|
|
|
|
}
|
|
|
|
|
|
|
|
get initialRotation() {
|
|
|
|
return this._initialized ? this._initialRotation : null;
|
|
|
|
}
|
|
|
|
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
_pushOrReplaceState(destination, forceReplace = false) {
|
2019-12-27 08:22:32 +09:00
|
|
|
const shouldReplace = forceReplace || !this._destination;
|
|
|
|
const newState = {
|
2019-12-03 20:04:49 +09:00
|
|
|
fingerprint: this._fingerprint,
|
2017-10-05 20:38:25 +09:00
|
|
|
uid: shouldReplace ? this._uid : this._uid + 1,
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
destination,
|
|
|
|
};
|
|
|
|
|
|
|
|
if (
|
|
|
|
typeof PDFJSDev !== "undefined" &&
|
|
|
|
PDFJSDev.test("CHROME") &&
|
2020-10-31 19:24:39 +09:00
|
|
|
window.history.state?.chromecomState
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
) {
|
|
|
|
// history.state.chromecomState is managed by chromecom.js.
|
|
|
|
newState.chromecomState = window.history.state.chromecomState;
|
|
|
|
}
|
|
|
|
this._updateInternalState(destination, newState.uid);
|
|
|
|
|
Add support for updating the document hash, off by default, when the browser history is updated (issue 5753)
This is *really* the best that we can do here, since other proposed solutions would interfere with (and break) the painstakingly implemented browsing history that's present in the default viewer.
I'm still not convinced that this is a good idea in general, but this patch implements it in a way where it is possible to toggle[1] for users that wish to have this feature. In particular, there's a couple of reasons why I'm not finding this feature necessary/great:
- It's already possible to easily obtain the current hash, by simply clicking on the `viewBookmark` button at any time.
- Hash changes requires a bit of special handling[2], i.e. extra code, to prevent issues when the browser history is traversed (see `PDFHistory._popState`). Currently this is only necessary when the user has manually changed the hash, with this patch it will always be the case (assuming the feature is active).
- It's not always possible to change the URL when updating the browser history. For example: In the Firefox built-in viewer, the URL cannot be modified for local files (i.e. those using the `file://` protocol).
This leads to inconsistent behaviour, and may in some cases even result in errors being thrown and the history thus not updating, if the browser prevents changes to the URL during `pushState`/`replaceState` calls.
---
[1] Using the `historyUpdateUrl` viewer preference.
[2] This depends, to a great extent, on browsers always firing `popstate` events *before* `hashchange` events, which may or may not actually be guaranteed.
2019-01-03 23:45:33 +09:00
|
|
|
let newUrl;
|
2020-10-31 19:24:39 +09:00
|
|
|
if (this._updateUrl && destination?.hash) {
|
2024-02-02 21:02:31 +09:00
|
|
|
const baseUrl = document.location.href.split("#", 1)[0];
|
2019-12-26 04:03:46 +09:00
|
|
|
// Prevent errors in Firefox.
|
Add support for updating the document hash, off by default, when the browser history is updated (issue 5753)
This is *really* the best that we can do here, since other proposed solutions would interfere with (and break) the painstakingly implemented browsing history that's present in the default viewer.
I'm still not convinced that this is a good idea in general, but this patch implements it in a way where it is possible to toggle[1] for users that wish to have this feature. In particular, there's a couple of reasons why I'm not finding this feature necessary/great:
- It's already possible to easily obtain the current hash, by simply clicking on the `viewBookmark` button at any time.
- Hash changes requires a bit of special handling[2], i.e. extra code, to prevent issues when the browser history is traversed (see `PDFHistory._popState`). Currently this is only necessary when the user has manually changed the hash, with this patch it will always be the case (assuming the feature is active).
- It's not always possible to change the URL when updating the browser history. For example: In the Firefox built-in viewer, the URL cannot be modified for local files (i.e. those using the `file://` protocol).
This leads to inconsistent behaviour, and may in some cases even result in errors being thrown and the history thus not updating, if the browser prevents changes to the URL during `pushState`/`replaceState` calls.
---
[1] Using the `historyUpdateUrl` viewer preference.
[2] This depends, to a great extent, on browsers always firing `popstate` events *before* `hashchange` events, which may or may not actually be guaranteed.
2019-01-03 23:45:33 +09:00
|
|
|
if (!baseUrl.startsWith("file://")) {
|
|
|
|
newUrl = `${baseUrl}#${destination.hash}`;
|
|
|
|
}
|
|
|
|
}
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
if (shouldReplace) {
|
2019-11-12 01:48:04 +09:00
|
|
|
window.history.replaceState(newState, "", newUrl);
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
} else {
|
2019-11-12 01:48:04 +09:00
|
|
|
window.history.pushState(newState, "", newUrl);
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
typeof PDFJSDev !== "undefined" &&
|
|
|
|
PDFJSDev.test("CHROME") &&
|
|
|
|
top === window
|
|
|
|
) {
|
|
|
|
// eslint-disable-next-line no-undef
|
|
|
|
chrome.runtime.sendMessage("showPageAction");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
*/
|
2017-07-20 22:57:26 +09:00
|
|
|
_tryPushCurrentPosition(temporary = false) {
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
if (!this._position) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let position = this._position;
|
2017-07-20 22:57:26 +09:00
|
|
|
if (temporary) {
|
2018-06-28 03:39:39 +09:00
|
|
|
position = Object.assign(Object.create(null), this._position);
|
2017-07-20 22:57:26 +09:00
|
|
|
position.temporary = true;
|
|
|
|
}
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
|
|
|
|
if (!this._destination) {
|
|
|
|
this._pushOrReplaceState(position);
|
|
|
|
return;
|
|
|
|
}
|
2017-07-20 22:57:26 +09:00
|
|
|
if (this._destination.temporary) {
|
|
|
|
// Always replace a previous *temporary* position.
|
|
|
|
this._pushOrReplaceState(position, /* forceReplace = */ true);
|
|
|
|
return;
|
|
|
|
}
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
if (this._destination.hash === position.hash) {
|
|
|
|
return; // The current document position has not changed.
|
|
|
|
}
|
2017-08-11 20:54:30 +09:00
|
|
|
if (
|
|
|
|
!this._destination.page &&
|
|
|
|
(POSITION_UPDATED_THRESHOLD <= 0 ||
|
|
|
|
this._numPositionUpdates <= POSITION_UPDATED_THRESHOLD)
|
|
|
|
) {
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
// `this._destination` was set through the user changing the hash of
|
|
|
|
// the document. Do not add `this._position` to the browser history,
|
|
|
|
// to avoid "flooding" it with lots of (nearly) identical entries,
|
|
|
|
// since we cannot ensure that the document position has changed.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let forceReplace = false;
|
2018-12-07 20:55:19 +09:00
|
|
|
if (
|
|
|
|
this._destination.page >= position.first &&
|
|
|
|
this._destination.page <= position.page
|
|
|
|
) {
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
// When the `page` of `this._destination` is still visible, do not
|
|
|
|
// update the browsing history when `this._destination` either:
|
|
|
|
// - contains an internal destination, since in this case we
|
|
|
|
// cannot ensure that the document position has actually changed.
|
|
|
|
// - was set through the user changing the hash of the document.
|
2021-03-25 06:07:29 +09:00
|
|
|
if (this._destination.dest !== undefined || !this._destination.first) {
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// To avoid "flooding" the browser history, replace the current entry.
|
|
|
|
forceReplace = true;
|
|
|
|
}
|
|
|
|
this._pushOrReplaceState(position, forceReplace);
|
|
|
|
}
|
|
|
|
|
2021-03-24 21:55:56 +09:00
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
_isValidPage(val) {
|
|
|
|
return (
|
|
|
|
Number.isInteger(val) && val > 0 && val <= this.linkService.pagesCount
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
*/
|
2019-01-07 00:39:43 +09:00
|
|
|
_isValidState(state, checkReload = false) {
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
if (!state) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-12-03 20:04:49 +09:00
|
|
|
if (state.fingerprint !== this._fingerprint) {
|
2019-01-07 00:39:43 +09:00
|
|
|
if (checkReload) {
|
|
|
|
// Potentially accept the history entry, even if the fingerprints don't
|
|
|
|
// match, when the viewer was reloaded (see issue 6847).
|
|
|
|
if (
|
|
|
|
typeof state.fingerprint !== "string" ||
|
2019-12-03 20:04:49 +09:00
|
|
|
state.fingerprint.length !== this._fingerprint.length
|
|
|
|
) {
|
2019-01-07 00:39:43 +09:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const [perfEntry] = performance.getEntriesByType("navigation");
|
2020-10-31 19:24:39 +09:00
|
|
|
if (perfEntry?.type !== "reload") {
|
2019-01-07 00:39:43 +09:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// This should only occur in viewers with support for opening more than
|
|
|
|
// one PDF document, e.g. the GENERIC viewer.
|
|
|
|
return false;
|
|
|
|
}
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
}
|
|
|
|
if (!Number.isInteger(state.uid) || state.uid < 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (state.destination === null || typeof state.destination !== "object") {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
*/
|
2017-07-20 22:57:26 +09:00
|
|
|
_updateInternalState(destination, uid, removeTemporary = false) {
|
2017-09-07 18:37:23 +09:00
|
|
|
if (this._updateViewareaTimeout) {
|
|
|
|
// When updating `this._destination`, make sure that we always wait for
|
|
|
|
// the next 'updateviewarea' event before (potentially) attempting to
|
|
|
|
// push the current position to the browser history.
|
|
|
|
clearTimeout(this._updateViewareaTimeout);
|
|
|
|
this._updateViewareaTimeout = null;
|
|
|
|
}
|
2020-10-31 19:24:39 +09:00
|
|
|
if (removeTemporary && destination?.temporary) {
|
2017-07-20 22:57:26 +09:00
|
|
|
// When the `destination` comes from the browser history,
|
|
|
|
// we no longer treat it as a *temporary* position.
|
|
|
|
delete destination.temporary;
|
|
|
|
}
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
this._destination = destination;
|
2017-10-05 20:38:25 +09:00
|
|
|
this._uid = uid;
|
2020-10-12 19:26:19 +09:00
|
|
|
this._maxUid = Math.max(this._maxUid, uid);
|
2017-08-11 20:54:30 +09:00
|
|
|
// This should always be reset when `this._destination` is updated.
|
|
|
|
this._numPositionUpdates = 0;
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
}
|
|
|
|
|
2019-12-04 00:29:14 +09:00
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
*/
|
2020-05-07 20:53:07 +09:00
|
|
|
_parseCurrentHash(checkNameddest = false) {
|
2019-12-04 00:29:14 +09:00
|
|
|
const hash = unescape(getCurrentHash()).substring(1);
|
2020-05-07 20:53:07 +09:00
|
|
|
const params = parseQueryString(hash);
|
|
|
|
|
2021-08-01 05:15:30 +09:00
|
|
|
const nameddest = params.get("nameddest") || "";
|
|
|
|
let page = params.get("page") | 0;
|
2019-12-04 00:29:14 +09:00
|
|
|
|
2021-03-24 21:55:56 +09:00
|
|
|
if (!this._isValidPage(page) || (checkNameddest && nameddest.length > 0)) {
|
2019-12-04 00:29:14 +09:00
|
|
|
page = null;
|
|
|
|
}
|
|
|
|
return { hash, page, rotation: this.linkService.rotation };
|
|
|
|
}
|
|
|
|
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
_updateViewarea({ location }) {
|
2017-07-20 22:57:26 +09:00
|
|
|
if (this._updateViewareaTimeout) {
|
|
|
|
clearTimeout(this._updateViewareaTimeout);
|
|
|
|
this._updateViewareaTimeout = null;
|
|
|
|
}
|
|
|
|
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
this._position = {
|
2022-04-05 20:56:51 +09:00
|
|
|
hash: location.pdfOpenParams.substring(1),
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
page: this.linkService.page,
|
|
|
|
first: location.pageNumber,
|
2017-08-21 18:56:49 +09:00
|
|
|
rotation: location.rotation,
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
};
|
|
|
|
|
|
|
|
if (this._popStateInProgress) {
|
|
|
|
return;
|
|
|
|
}
|
2017-07-20 22:57:26 +09:00
|
|
|
|
2017-08-11 20:54:30 +09:00
|
|
|
if (
|
|
|
|
POSITION_UPDATED_THRESHOLD > 0 &&
|
|
|
|
this._isPagesLoaded &&
|
|
|
|
this._destination &&
|
|
|
|
!this._destination.page
|
|
|
|
) {
|
|
|
|
// If the current destination was set through the user changing the hash
|
|
|
|
// of the document, we will usually not try to push the current position
|
|
|
|
// to the browser history; see `this._tryPushCurrentPosition()`.
|
|
|
|
//
|
|
|
|
// To prevent `this._tryPushCurrentPosition()` from effectively being
|
|
|
|
// reduced to a no-op in this case, we will assume that the position
|
|
|
|
// *did* in fact change if the 'updateviewarea' event was dispatched
|
|
|
|
// more than `POSITION_UPDATED_THRESHOLD` times.
|
|
|
|
this._numPositionUpdates++;
|
|
|
|
}
|
|
|
|
|
2017-07-20 22:57:26 +09:00
|
|
|
if (UPDATE_VIEWAREA_TIMEOUT > 0) {
|
|
|
|
// When closing the browser, a 'pagehide' event will be dispatched which
|
|
|
|
// *should* allow us to push the current position to the browser history.
|
|
|
|
// In practice, it seems that the event is arriving too late in order for
|
|
|
|
// the session history to be successfully updated.
|
|
|
|
// (For additional details, please refer to the discussion in
|
|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1153393.)
|
|
|
|
//
|
|
|
|
// To workaround this we attempt to *temporarily* add the current position
|
|
|
|
// to the browser history only when the viewer is *idle*,
|
|
|
|
// i.e. when scrolling and/or zooming does not occur.
|
|
|
|
//
|
|
|
|
// PLEASE NOTE: It's absolutely imperative that the browser history is
|
|
|
|
// *not* updated too often, since that would render the viewer more or
|
|
|
|
// less unusable. Hence the use of a timeout to delay the update until
|
|
|
|
// the viewer has been idle for `UPDATE_VIEWAREA_TIMEOUT` milliseconds.
|
|
|
|
this._updateViewareaTimeout = setTimeout(() => {
|
|
|
|
if (!this._popStateInProgress) {
|
|
|
|
this._tryPushCurrentPosition(/* temporary = */ true);
|
|
|
|
}
|
|
|
|
this._updateViewareaTimeout = null;
|
|
|
|
}, UPDATE_VIEWAREA_TIMEOUT);
|
|
|
|
}
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
_popState({ state }) {
|
2019-12-27 08:22:32 +09:00
|
|
|
const newHash = getCurrentHash(),
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
hashChanged = this._currentHash !== newHash;
|
|
|
|
this._currentHash = newHash;
|
|
|
|
|
2019-12-04 04:53:00 +09:00
|
|
|
if (
|
|
|
|
(typeof PDFJSDev !== "undefined" &&
|
|
|
|
PDFJSDev.test("CHROME") &&
|
2020-10-31 19:24:39 +09:00
|
|
|
state?.chromecomState &&
|
2019-12-04 04:53:00 +09:00
|
|
|
!this._isValidState(state)) ||
|
|
|
|
!state
|
|
|
|
) {
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
// This case corresponds to the user changing the hash of the document.
|
2017-10-05 20:38:25 +09:00
|
|
|
this._uid++;
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
|
2019-12-04 00:29:14 +09:00
|
|
|
const { hash, page, rotation } = this._parseCurrentHash();
|
2017-08-21 18:56:49 +09:00
|
|
|
this._pushOrReplaceState(
|
|
|
|
{ hash, page, rotation },
|
|
|
|
/* forceReplace = */ true
|
|
|
|
);
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!this._isValidState(state)) {
|
|
|
|
// This should only occur in viewers with support for opening more than
|
|
|
|
// one PDF document, e.g. the GENERIC viewer.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prevent the browser history from updating until the new destination,
|
|
|
|
// as stored in the browser history, has been scrolled into view.
|
|
|
|
this._popStateInProgress = true;
|
|
|
|
|
|
|
|
if (hashChanged) {
|
|
|
|
// When the hash changed, implying that the 'popstate' event will be
|
|
|
|
// followed by a 'hashchange' event, then we do *not* want to update the
|
|
|
|
// browser history when handling the 'hashchange' event (in web/app.js)
|
|
|
|
// since that would *overwrite* the new destination navigated to below.
|
|
|
|
//
|
|
|
|
// To avoid accidentally disabling all future user-initiated hash changes,
|
|
|
|
// if there's e.g. another 'hashchange' listener that stops the event
|
|
|
|
// propagation, we make sure to always force-reset `this._blockHashChange`
|
|
|
|
// after `HASH_CHANGE_TIMEOUT` milliseconds have passed.
|
|
|
|
this._blockHashChange++;
|
|
|
|
waitOnEventOrTimeout({
|
|
|
|
target: window,
|
|
|
|
name: "hashchange",
|
|
|
|
delay: HASH_CHANGE_TIMEOUT,
|
|
|
|
}).then(() => {
|
|
|
|
this._blockHashChange--;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Navigate to the new destination.
|
2019-12-27 08:22:32 +09:00
|
|
|
const destination = state.destination;
|
2017-07-20 22:57:26 +09:00
|
|
|
this._updateInternalState(
|
|
|
|
destination,
|
|
|
|
state.uid,
|
|
|
|
/* removeTemporary = */ true
|
|
|
|
);
|
2017-08-21 18:56:49 +09:00
|
|
|
|
|
|
|
if (isValidRotation(destination.rotation)) {
|
|
|
|
this.linkService.rotation = destination.rotation;
|
|
|
|
}
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
if (destination.dest) {
|
2020-10-04 00:43:33 +09:00
|
|
|
this.linkService.goToDestination(destination.dest);
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
} else if (destination.hash) {
|
|
|
|
this.linkService.setHash(destination.hash);
|
|
|
|
} else if (destination.page) {
|
|
|
|
// Fallback case; shouldn't be necessary, but better safe than sorry.
|
|
|
|
this.linkService.page = destination.page;
|
|
|
|
}
|
|
|
|
|
2020-10-04 00:43:33 +09:00
|
|
|
// Since `PDFLinkService.goToDestination` is asynchronous, we thus defer the
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
// resetting of `this._popStateInProgress` slightly.
|
|
|
|
Promise.resolve().then(() => {
|
|
|
|
this._popStateInProgress = false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-12-03 20:04:49 +09:00
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
_pageHide() {
|
|
|
|
// Attempt to push the `this._position` into the browser history when
|
|
|
|
// navigating away from the document. This is *only* done if the history
|
|
|
|
// is empty/temporary, since otherwise an existing browser history entry
|
|
|
|
// will end up being overwritten (given that new entries cannot be pushed
|
|
|
|
// into the browser history when the 'unload' event has already fired).
|
|
|
|
if (!this._destination || this._destination.temporary) {
|
|
|
|
this._tryPushCurrentPosition();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
_bindEvents() {
|
2019-12-03 20:04:49 +09:00
|
|
|
if (this._boundEvents) {
|
|
|
|
return; // The event listeners were already added.
|
|
|
|
}
|
|
|
|
this._boundEvents = {
|
|
|
|
updateViewarea: this._updateViewarea.bind(this),
|
|
|
|
popState: this._popState.bind(this),
|
|
|
|
pageHide: this._pageHide.bind(this),
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
};
|
|
|
|
|
Re-factor the `EventBus` to allow servicing of "external" event listeners *after* the viewer components have updated
Since the goal has always been, essentially since the `EventBus` abstraction was added, to remove all dispatching of DOM events[1] from the viewer components this patch tries to address one thing that came up when updating the examples:
The DOM events are always dispatched last, and it's thus guaranteed that all internal event listeners have been invoked first.
However, there's no such guarantees with the general `EventBus` functionality and the order in which event listeners are invoked is *not* specified. With the promotion of the `EventBus` in the examples, over DOM events, it seems like a good idea to at least *try* to keep this ordering invariant[2] intact.
Obviously this won't prevent anyone from manually calling the new *internal* viewer component methods on the `EventBus`, but hopefully that won't be too common since any existing third-party code would obviously use the `on`/`off` methods and that all of the examples shows the *correct* usage (which should be similarily documented on the "Third party viewer usage" Wiki-page).
---
[1] Looking at the various Firefox-tests, I'm not sure that it'll be possible to (easily) re-write all of them to not rely on DOM events (since getting access to `PDFViewerApplication` might be generally difficult/messy depending on scopes).
In any case, even if technically feasible, it would most likely add *a lot* of complication that may not be desireable in the various Firefox-tests. All-in-all, I'd be fine with keeping the DOM events only for the `MOZCENTRAL` target and gated on `Cu.isInAutomation` (or similar) rather than a preference.
[2] I wouldn't expect any *real* bugs in a custom implementation, simply based on event ordering, but it nonetheless seem like a good idea if any "external" events are still handled last.
2020-02-27 07:33:27 +09:00
|
|
|
this.eventBus._on("updateviewarea", this._boundEvents.updateViewarea);
|
2019-12-03 20:04:49 +09:00
|
|
|
window.addEventListener("popstate", this._boundEvents.popState);
|
|
|
|
window.addEventListener("pagehide", this._boundEvents.pageHide);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
_unbindEvents() {
|
|
|
|
if (!this._boundEvents) {
|
|
|
|
return; // The event listeners were already removed.
|
|
|
|
}
|
Re-factor the `EventBus` to allow servicing of "external" event listeners *after* the viewer components have updated
Since the goal has always been, essentially since the `EventBus` abstraction was added, to remove all dispatching of DOM events[1] from the viewer components this patch tries to address one thing that came up when updating the examples:
The DOM events are always dispatched last, and it's thus guaranteed that all internal event listeners have been invoked first.
However, there's no such guarantees with the general `EventBus` functionality and the order in which event listeners are invoked is *not* specified. With the promotion of the `EventBus` in the examples, over DOM events, it seems like a good idea to at least *try* to keep this ordering invariant[2] intact.
Obviously this won't prevent anyone from manually calling the new *internal* viewer component methods on the `EventBus`, but hopefully that won't be too common since any existing third-party code would obviously use the `on`/`off` methods and that all of the examples shows the *correct* usage (which should be similarily documented on the "Third party viewer usage" Wiki-page).
---
[1] Looking at the various Firefox-tests, I'm not sure that it'll be possible to (easily) re-write all of them to not rely on DOM events (since getting access to `PDFViewerApplication` might be generally difficult/messy depending on scopes).
In any case, even if technically feasible, it would most likely add *a lot* of complication that may not be desireable in the various Firefox-tests. All-in-all, I'd be fine with keeping the DOM events only for the `MOZCENTRAL` target and gated on `Cu.isInAutomation` (or similar) rather than a preference.
[2] I wouldn't expect any *real* bugs in a custom implementation, simply based on event ordering, but it nonetheless seem like a good idea if any "external" events are still handled last.
2020-02-27 07:33:27 +09:00
|
|
|
this.eventBus._off("updateviewarea", this._boundEvents.updateViewarea);
|
2019-12-03 20:04:49 +09:00
|
|
|
window.removeEventListener("popstate", this._boundEvents.popState);
|
|
|
|
window.removeEventListener("pagehide", this._boundEvents.pageHide);
|
|
|
|
|
|
|
|
this._boundEvents = null;
|
Re-write `PDFHistory` from scratch
This patch completely re-implements `PDFHistory` to get rid of various bugs currently present, and to hopefully make maintenance slightly easier. Most of the interface is similar to the existing one, but it should be somewhat simplified.
The new implementation should be more robust against failure, compared to the old one. Previously, it was too easy to end up in a state which basically caused the browser history to lock-up, preventing the user from navigating back/forward. (In the new implementation, the browser history should not be updated rather than breaking if things go wrong.)
Given that the code has to deal with various edge-cases, it's still not as simple as I would have liked, but it should now be somewhat easier to deal with.
The main source of complication in the code is actually that we allow the user to change the hash of a already loaded document (we'll no longer try to navigate back-and-forth in this case, since the next commit contains a workaround).
In the new code, there's also *a lot* more comments (perhaps too many?) to attempt to explain the logic. This is something that the old implementation was serverly lacking, which is a one of the reasons why it was so difficult to maintain.
One particular thing to note is that the new code uses the `pagehide` event rather than `beforeunload`, since the latter seems to be a bad idea based on https://bugzilla.mozilla.org/show_bug.cgi?id=1336763.
2017-07-16 20:39:39 +09:00
|
|
|
}
|
2017-07-14 21:24:32 +09:00
|
|
|
}
|
2015-04-27 23:04:11 +09:00
|
|
|
|
2017-10-10 01:00:26 +09:00
|
|
|
function isDestHashesEqual(destHash, pushHash) {
|
|
|
|
if (typeof destHash !== "string" || typeof pushHash !== "string") {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (destHash === pushHash) {
|
|
|
|
return true;
|
|
|
|
}
|
2021-08-01 05:15:30 +09:00
|
|
|
const nameddest = parseQueryString(destHash).get("nameddest");
|
2017-10-10 01:00:26 +09:00
|
|
|
if (nameddest === pushHash) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
function isDestArraysEqual(firstDest, secondDest) {
|
2017-08-14 00:11:49 +09:00
|
|
|
function isEntryEqual(first, second) {
|
|
|
|
if (typeof first !== typeof second) {
|
|
|
|
return false;
|
|
|
|
}
|
2018-07-09 20:11:35 +09:00
|
|
|
if (Array.isArray(first) || Array.isArray(second)) {
|
2017-08-14 00:11:49 +09:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (first !== null && typeof first === "object" && second !== null) {
|
|
|
|
if (Object.keys(first).length !== Object.keys(second).length) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-12-27 08:22:32 +09:00
|
|
|
for (const key in first) {
|
2017-08-14 00:11:49 +09:00
|
|
|
if (!isEntryEqual(first[key], second[key])) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return first === second || (Number.isNaN(first) && Number.isNaN(second));
|
|
|
|
}
|
|
|
|
|
2018-07-09 20:11:35 +09:00
|
|
|
if (!(Array.isArray(firstDest) && Array.isArray(secondDest))) {
|
2017-08-14 00:11:49 +09:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (firstDest.length !== secondDest.length) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for (let i = 0, ii = firstDest.length; i < ii; i++) {
|
|
|
|
if (!isEntryEqual(firstDest[i], secondDest[i])) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-01-09 23:37:44 +09:00
|
|
|
export { isDestArraysEqual, isDestHashesEqual, PDFHistory };
|