Compare commits

..

2 Commits

Author SHA1 Message Date
Veloman Yunkan
035667b0e1 fixup! Fixed external links in the viewer iframe 2023-05-03 16:56:55 +04:00
Veloman Yunkan
d2b014656b Fixed external links in the viewer iframe
Before this fix clicking an external link in the viewer iframe had no
effect (other than an error being reported in the browser dev tools
console) because the attempt to navigate the top browser context was
suppressed due to sandboxing.
2023-05-02 19:20:38 +04:00
4 changed files with 17 additions and 36 deletions

View File

@@ -1088,6 +1088,7 @@ const std::string CONTENT_CSP_HEADER =
"sandbox allow-scripts "
"allow-same-origin "
"allow-top-navigation-by-user-activation "
"allow-modals "
"allow-popups "
"allow-forms "

View File

@@ -23,7 +23,7 @@ function userUrl2IframeUrl(url) {
}
function getBookFromUserUrl(url) {
if ( url == '' || url.startsWith('catch/external?') ) {
if ( url == '' ) {
return null;
}
@@ -131,10 +131,6 @@ function iframeUrl2UserUrl(url, query) {
return '';
}
if ( url == `${root}/catch/external` ) {
return `catch/external${query}`;
}
if ( url == `${root}/search` ) {
return `search${query}`;
}
@@ -224,16 +220,12 @@ function handle_location_hash_change() {
function handle_content_url_change() {
const iframeLocation = contentIframe.contentWindow.location;
console.log('handle_content_url_change: ' + iframeLocation.href);
document.title = contentIframe.contentDocument.title;
const iframeContentUrl = iframeLocation.pathname;
const iframeContentQuery = iframeLocation.search;
const newHash = iframeUrl2UserUrl(iframeContentUrl, iframeContentQuery);
if ( newHash.startsWith('catch/external?') ) {
handleInterceptedExternalLink(newHash);
} else {
document.title = contentIframe.contentDocument.title;
history.replaceState(viewerState, null, makeURL(location.search, newHash));
updateCurrentBookIfNeeded(newHash);
}
history.replaceState(viewerState, null, makeURL(location.search, newHash));
updateCurrentBookIfNeeded(newHash);
};
////////////////////////////////////////////////////////////////////////////////
@@ -265,12 +257,17 @@ function isExternalUrl(url) {
|| url.startsWith("https:");
}
function onClickEvent(e) {
function handleLinkClick(e) {
const iframeDocument = contentIframe.contentDocument;
const target = matchingAncestorElement(e.target, iframeDocument, "a");
if (target !== null && "href" in target) {
if ( isExternalUrl(target.href) ) {
return blockLink(target);
target.setAttribute("target", "_top");
if ( viewerSettings.linkBlockingEnabled ) {
return blockLink(target);
}
} else {
target.setAttribute("target", "content_iframe");
}
}
}
@@ -306,25 +303,7 @@ this.Element && function(ElementPrototype) {
}(Element.prototype);
function setup_external_link_blocker() {
setupEventHandler(contentIframe.contentDocument, 'a', 'click', onClickEvent);
}
function getBlockedUrl(catchExternalUrl) {
const p = new URLSearchParams(catchExternalUrl.split('?')[1]);
return p.get('source');
}
function handleInterceptedExternalLink(catchExternalUrl) {
// The external link blocking page was loaded in the viewer iframe.
// We need to get rid of the viewer taskbar and load in the top frame either
// the external resource or, if running in --blockexternal mode, the
// confirmation page
const url = viewerSettings.linkBlockingEnabled
? `${root}/` + catchExternalUrl
: getBlockedUrl(catchExternalUrl);
history.back(); // drop from the browsing history the state where the
// external link catcher page is loaded in the iframe ...
window.location = url; // ... and load the target in the top frame instead
setupEventHandler(contentIframe.contentDocument, 'a', 'click', handleLinkClick);
}
////////////////////////////////////////////////////////////////////////////////
@@ -336,8 +315,8 @@ let viewerSetupComplete = false;
function on_content_load() {
if ( viewerSetupComplete ) {
handle_content_url_change();
setup_external_link_blocker();
}
setup_external_link_blocker();
}
function htmlDecode(input) {

View File

@@ -69,6 +69,7 @@
</div>
<iframe id="content_iframe"
name="content_iframe"
referrerpolicy="no-referrer"
onload="on_content_load()"
src="./skin/blank.html?KIWIXCACHEID" title="ZIM content" width="100%"

View File

@@ -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=db02f59d" },
{ STATIC_CONTENT, "/ROOT%23%3F/skin/viewer.js?cacheid=b548ad94" },
{ 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( <link type="text/css" href="./skin/taskbar.css?cacheid=bbda
<link type="text/css" href="./skin/css/autoComplete.css?cacheid=08951e06" rel="Stylesheet" />
<script type="module" src="./skin/i18n.js?cacheid=2cf0f8c5" defer></script>
<script type="text/javascript" src="./skin/languages.js?cacheid=b00b12db" defer></script>
<script type="text/javascript" src="./skin/viewer.js?cacheid=db02f59d" defer></script>
<script type="text/javascript" src="./skin/viewer.js?cacheid=b548ad94" defer></script>
<script type="text/javascript" src="./skin/autoComplete.min.js?cacheid=1191aaaf"></script>
const blankPageUrl = root + "/skin/blank.html?cacheid=6b1fa032";
<img src="./skin/langSelector.svg?cacheid=00b59961">