diff --git a/static/skin/viewer.js b/static/skin/viewer.js
index 2c3c80a14..a850b6693 100644
--- a/static/skin/viewer.js
+++ b/static/skin/viewer.js
@@ -204,14 +204,30 @@ function handle_visual_viewport_change() {
contentIframe.height = wh - contentIframe.offsetTop - 4;
}
+function setIframeUrl(path) {
+ try {
+ // Don't do anything if we are already at the requested URL.
+ // This is needed to break the infinite ping-pong played by
+ // handle_location_hash_change() and handle_content_url_change()
+ // (when either top-window or content window/iframe URL changes the other
+ // one is updated too).
+ if ( path == contentIframe.contentWindow.location.pathname )
+ return;
+ } catch ( error ) {
+ // This happens in Firefox when a PDF file is displayed in the iframe
+ // (sandboxing of the iframe content and cross-origin mismatch with the
+ // builtin PDF viewer result in preventing access to the attributes of
+ // contentIframe.contentWindow.location).
+ // Fall through and load the requested URL.
+ }
+ contentIframe.contentWindow.location.replace(path);
+}
+
function handle_location_hash_change() {
const hash = window.location.hash.slice(1);
console.log("handle_location_hash_change: " + hash);
updateCurrentBookIfNeeded(hash);
- const iframeContentUrl = userUrl2IframeUrl(hash);
- if ( iframeContentUrl != contentIframe.contentWindow.location.pathname ) {
- contentIframe.contentWindow.location.replace(iframeContentUrl);
- }
+ setIframeUrl(userUrl2IframeUrl(hash));
updateSearchBoxForLocationChange();
previousScrollTop = Infinity;
history.replaceState(viewerState, null);
diff --git a/test/server.cpp b/test/server.cpp
index b5642719d..b48b488e2 100644
--- a/test/server.cpp
+++ b/test/server.cpp
@@ -73,7 +73,7 @@ const ResourceCollection resources200Compressible{
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/taskbar.css" },
{ STATIC_CONTENT, "/ROOT%23%3F/skin/taskbar.css?cacheid=bbdaf425" },
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/viewer.js" },
- { STATIC_CONTENT, "/ROOT%23%3F/skin/viewer.js?cacheid=b9a574d4" },
+ { STATIC_CONTENT, "/ROOT%23%3F/skin/viewer.js?cacheid=725c95a2" },
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/fonts/Poppins.ttf" },
{ STATIC_CONTENT, "/ROOT%23%3F/skin/fonts/Poppins.ttf?cacheid=af705837" },
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/fonts/Roboto.ttf" },
@@ -312,7 +312,7 @@ R"EXPECTEDRESULT(
-
+
const blankPageUrl = root + "/skin/blank.html?cacheid=6b1fa032";