From c1ad65d515b053a618c019a31a3e82138945dc3b Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Fri, 21 Apr 2023 17:44:04 +0400 Subject: [PATCH] PDF-friendly book home button in the viewer In firefox, when PDF content is displayed in the viewer, changing the viewer URL in the address bar had no effect. The most prominent manifestation of this bug was the broken book home button but the same issue was present even if the fragment component of the viewer URL was edited manually. The bug was a result of 1. an optimization preventing any actions if the new content URL is the same as the old content URL (this was needed to break the infinite loop of mutual updates of the top-window and content window/iframe URLs when any one of them changes). 2. sandboxing of the iframe and inability to access the content URL in iframe because of cross-origin restrictions when the content is a PDF displayed by the builtin viewer. Now that issue is fixed. A slight remaining defect is that the addressbar URL is still not updated when a PDF file is loaded/displayed in the viewer. --- static/skin/viewer.js | 24 ++++++++++++++++++++---- test/server.cpp | 4 ++-- 2 files changed, 22 insertions(+), 6 deletions(-) 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";