mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Browser viewer: Do not fail if the book contains javascript that has errors. Fixes #1715781 [Private bug](https://bugs.launchpad.net/calibre/+bug/1715781)
This commit is contained in:
parent
ccc6c5d988
commit
cca87e7ad2
@ -69,6 +69,7 @@ class IframeBoss:
|
|||||||
self.replace_history_on_next_cfi_update = True
|
self.replace_history_on_next_cfi_update = True
|
||||||
self.encrypted_communications = False
|
self.encrypted_communications = False
|
||||||
self.blob_url_map = {}
|
self.blob_url_map = {}
|
||||||
|
self.resource_urls = {}
|
||||||
self.content_ready = False
|
self.content_ready = False
|
||||||
self.last_window_width = self.last_window_height = -1
|
self.last_window_width = self.last_window_height = -1
|
||||||
window.addEventListener('message', self.handle_message, False)
|
window.addEventListener('message', self.handle_message, False)
|
||||||
@ -145,15 +146,19 @@ class IframeBoss:
|
|||||||
# type of error
|
# type of error
|
||||||
console.log(f'Unhandled error from external javascript, ignoring: {msg} {script_url} {line_number}')
|
console.log(f'Unhandled error from external javascript, ignoring: {msg} {script_url} {line_number}')
|
||||||
return
|
return
|
||||||
console.log(error_object)
|
is_internal_error = not self.resource_urls[script_url]
|
||||||
try:
|
if is_internal_error: # dont report errors from scripts in the book itself
|
||||||
fname = script_url.rpartition('/')[-1] or script_url
|
console.log(error_object)
|
||||||
msg = msg + '<br><span style="font-size:smaller">' + 'Error at {}:{}:{}'.format(fname, line_number, column_number or '') + '</span>'
|
try:
|
||||||
details = traceback.format_exception(error_object).join('') if error_object else ''
|
fname = script_url.rpartition('/')[-1] or script_url
|
||||||
self.send_message('error', title=_('Unhandled error'), details=details, msg=msg)
|
msg = msg + '<br><span style="font-size:smaller">' + 'Error at {}:{}:{}'.format(fname, line_number, column_number or '') + '</span>'
|
||||||
return True
|
details = traceback.format_exception(error_object).join('') if error_object else ''
|
||||||
except:
|
self.send_message('error', title=_('Unhandled error'), details=details, msg=msg)
|
||||||
console.log('There was an error in the iframe unhandled exception handler')
|
return True
|
||||||
|
except:
|
||||||
|
console.log('There was an error in the iframe unhandled exception handler')
|
||||||
|
else:
|
||||||
|
(console.error or console.log)('There was an error in the JavaScript from within the book')
|
||||||
|
|
||||||
def display(self, data):
|
def display(self, data):
|
||||||
self.length_before = None
|
self.length_before = None
|
||||||
@ -186,7 +191,7 @@ class IframeBoss:
|
|||||||
for name in self.blob_url_map:
|
for name in self.blob_url_map:
|
||||||
window.URL.revokeObjectURL(self.blob_url_map[name])
|
window.URL.revokeObjectURL(self.blob_url_map[name])
|
||||||
root_data, self.mathjax, self.blob_url_map = finalize_resources(self.book, data.name, data.resource_data)
|
root_data, self.mathjax, self.blob_url_map = finalize_resources(self.book, data.name, data.resource_data)
|
||||||
unserialize_html(root_data, self.content_loaded)
|
self.resource_urls = unserialize_html(root_data, self.content_loaded)
|
||||||
|
|
||||||
def handle_gesture(self, gesture):
|
def handle_gesture(self, gesture):
|
||||||
if gesture.type is 'show-chrome':
|
if gesture.type is 'show-chrome':
|
||||||
|
@ -185,7 +185,7 @@ def apply_attributes(src, elem, ns_map):
|
|||||||
else:
|
else:
|
||||||
elem.setAttribute(a[0], a[1])
|
elem.setAttribute(a[0], a[1])
|
||||||
|
|
||||||
def process_stack(stack, tag_map, ns_map, load_required, onload):
|
def process_stack(stack, tag_map, ns_map, load_required, onload, resource_urls):
|
||||||
while stack.length:
|
while stack.length:
|
||||||
node, parent = stack.pop()
|
node, parent = stack.pop()
|
||||||
src = tag_map[node[0]]
|
src = tag_map[node[0]]
|
||||||
@ -194,13 +194,14 @@ def process_stack(stack, tag_map, ns_map, load_required, onload):
|
|||||||
else:
|
else:
|
||||||
elem = document.createElement(src.n)
|
elem = document.createElement(src.n)
|
||||||
loadable = False
|
loadable = False
|
||||||
if src.n in resource_tag_names:
|
attr = resource_tag_names[src.n]
|
||||||
attr = resource_tag_names[src.n]
|
if attr:
|
||||||
if attr.indexOf(':') != -1:
|
if attr.indexOf(':') != -1:
|
||||||
attr = attr.replace('xlink:', '')
|
attr = attr.replace('xlink:', '')
|
||||||
for a in (src.a or v'[]'):
|
for a in (src.a or v'[]'):
|
||||||
if a[0] is attr:
|
if a[0] is attr:
|
||||||
loadable = a[1].startswith('blob:')
|
loadable = a[1].startswith('blob:')
|
||||||
|
resource_urls[a[1]] = True
|
||||||
break
|
break
|
||||||
if loadable:
|
if loadable:
|
||||||
load_required.add(node[0])
|
load_required.add(node[0])
|
||||||
@ -227,6 +228,7 @@ def unserialize_html(serialized_data, proceed):
|
|||||||
apply_attributes(html, document.documentElement, ns_map)
|
apply_attributes(html, document.documentElement, ns_map)
|
||||||
head, body = tree[1], tree[2] # noqa: unused-local
|
head, body = tree[1], tree[2] # noqa: unused-local
|
||||||
clear(document.head, document.body)
|
clear(document.head, document.body)
|
||||||
|
resource_urls = {}
|
||||||
load_required = set()
|
load_required = set()
|
||||||
proceeded = False
|
proceeded = False
|
||||||
hang_timeout = 5
|
hang_timeout = 5
|
||||||
@ -248,14 +250,14 @@ def unserialize_html(serialized_data, proceed):
|
|||||||
stack = v'[]'
|
stack = v'[]'
|
||||||
for v'var i = head.length - 1; i >= 1; i--':
|
for v'var i = head.length - 1; i >= 1; i--':
|
||||||
stack.push(v'[head[i], document.head]')
|
stack.push(v'[head[i], document.head]')
|
||||||
process_stack(stack, tag_map, ns_map, load_required, onload)
|
process_stack(stack, tag_map, ns_map, load_required, onload, resource_urls)
|
||||||
bnode = tag_map[body[0]]
|
bnode = tag_map[body[0]]
|
||||||
apply_attributes(bnode, document.body, ns_map)
|
apply_attributes(bnode, document.body, ns_map)
|
||||||
if bnode.x:
|
if bnode.x:
|
||||||
document.body.appendChild(document.createTextNode(bnode.x))
|
document.body.appendChild(document.createTextNode(bnode.x))
|
||||||
for v'var i = body.length - 1; i >= 1; i--': # noqa: unused-local
|
for v'var i = body.length - 1; i >= 1; i--': # noqa: unused-local
|
||||||
stack.push(v'[body[i], document.body]')
|
stack.push(v'[body[i], document.body]')
|
||||||
process_stack(stack, tag_map, ns_map, load_required, onload)
|
process_stack(stack, tag_map, ns_map, load_required, onload, resource_urls)
|
||||||
ev = document.createEvent('Event')
|
ev = document.createEvent('Event')
|
||||||
ev.initEvent('DOMContentLoaded', True, True)
|
ev.initEvent('DOMContentLoaded', True, True)
|
||||||
document.dispatchEvent(ev)
|
document.dispatchEvent(ev)
|
||||||
@ -264,6 +266,7 @@ def unserialize_html(serialized_data, proceed):
|
|||||||
else:
|
else:
|
||||||
proceeded = True
|
proceeded = True
|
||||||
proceed()
|
proceed()
|
||||||
|
return resource_urls
|
||||||
|
|
||||||
def text_from_serialized_html(data):
|
def text_from_serialized_html(data):
|
||||||
serialized_data = JSON.parse(data)
|
serialized_data = JSON.parse(data)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user