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:
Kovid Goyal 2017-09-10 06:39:41 +05:30
parent ccc6c5d988
commit cca87e7ad2
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 23 additions and 15 deletions

View File

@ -69,6 +69,7 @@ class IframeBoss:
self.replace_history_on_next_cfi_update = True
self.encrypted_communications = False
self.blob_url_map = {}
self.resource_urls = {}
self.content_ready = False
self.last_window_width = self.last_window_height = -1
window.addEventListener('message', self.handle_message, False)
@ -145,15 +146,19 @@ class IframeBoss:
# type of error
console.log(f'Unhandled error from external javascript, ignoring: {msg} {script_url} {line_number}')
return
console.log(error_object)
try:
fname = script_url.rpartition('/')[-1] or script_url
msg = msg + '<br><span style="font-size:smaller">' + 'Error at {}:{}:{}'.format(fname, line_number, column_number or '') + '</span>'
details = traceback.format_exception(error_object).join('') if error_object else ''
self.send_message('error', title=_('Unhandled error'), details=details, msg=msg)
return True
except:
console.log('There was an error in the iframe unhandled exception handler')
is_internal_error = not self.resource_urls[script_url]
if is_internal_error: # dont report errors from scripts in the book itself
console.log(error_object)
try:
fname = script_url.rpartition('/')[-1] or script_url
msg = msg + '<br><span style="font-size:smaller">' + 'Error at {}:{}:{}'.format(fname, line_number, column_number or '') + '</span>'
details = traceback.format_exception(error_object).join('') if error_object else ''
self.send_message('error', title=_('Unhandled error'), details=details, msg=msg)
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):
self.length_before = None
@ -186,7 +191,7 @@ class IframeBoss:
for name in self.blob_url_map:
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)
unserialize_html(root_data, self.content_loaded)
self.resource_urls = unserialize_html(root_data, self.content_loaded)
def handle_gesture(self, gesture):
if gesture.type is 'show-chrome':

View File

@ -185,7 +185,7 @@ def apply_attributes(src, elem, ns_map):
else:
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:
node, parent = stack.pop()
src = tag_map[node[0]]
@ -194,13 +194,14 @@ def process_stack(stack, tag_map, ns_map, load_required, onload):
else:
elem = document.createElement(src.n)
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:
attr = attr.replace('xlink:', '')
for a in (src.a or v'[]'):
if a[0] is attr:
loadable = a[1].startswith('blob:')
resource_urls[a[1]] = True
break
if loadable:
load_required.add(node[0])
@ -227,6 +228,7 @@ def unserialize_html(serialized_data, proceed):
apply_attributes(html, document.documentElement, ns_map)
head, body = tree[1], tree[2] # noqa: unused-local
clear(document.head, document.body)
resource_urls = {}
load_required = set()
proceeded = False
hang_timeout = 5
@ -248,14 +250,14 @@ def unserialize_html(serialized_data, proceed):
stack = v'[]'
for v'var i = head.length - 1; i >= 1; i--':
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]]
apply_attributes(bnode, document.body, ns_map)
if bnode.x:
document.body.appendChild(document.createTextNode(bnode.x))
for v'var i = body.length - 1; i >= 1; i--': # noqa: unused-local
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.initEvent('DOMContentLoaded', True, True)
document.dispatchEvent(ev)
@ -264,6 +266,7 @@ def unserialize_html(serialized_data, proceed):
else:
proceeded = True
proceed()
return resource_urls
def text_from_serialized_html(data):
serialized_data = JSON.parse(data)