20
20
from splash .qtutils import (OPERATION_QT_CONSTANTS , WrappedSignal , qt2py ,
21
21
qurl2ascii , to_qurl )
22
22
from splash .render_options import validate_size_str
23
- from splash .qwebpage import SplashQWebPage , SplashQWebView
23
+ from splash .qwebpage import SplashQWebPage , SplashQWebView , RenderErrorInfo
24
24
from splash .exceptions import JsError , OneShotCallbackError
25
25
from splash .utils import to_bytes , escape_js
26
26
@@ -64,6 +64,9 @@ def __init__(self, network_manager, splash_proxy_factory, verbosity,
64
64
self ._callback_proxies_to_cancel = weakref .WeakSet ()
65
65
self ._js_console = None
66
66
self ._autoload_scripts = []
67
+ self ._is_unsupported_content = False
68
+ self ._unsupported_content_reply = None
69
+ self ._load_finished_after_unsupported_content_ready = False
67
70
68
71
self .logger = _BrowserTabLogger (uid = self ._uid , verbosity = verbosity )
69
72
self ._init_webpage (verbosity , network_manager , splash_proxy_factory ,
@@ -133,6 +136,8 @@ def _setup_webpage_events(self):
133
136
self .web_page .mainFrame ().loadFinished .connect (self ._on_load_finished )
134
137
self .web_page .mainFrame ().urlChanged .connect (self ._on_url_changed )
135
138
self .web_page .mainFrame ().javaScriptWindowObjectCleared .connect (self ._on_javascript_window_object_cleared )
139
+ self .web_page .setForwardUnsupportedContent (True )
140
+ self .web_page .unsupportedContent .connect (self ._on_unsupported_content )
136
141
self .logger .add_web_page (self .web_page )
137
142
138
143
def return_result (self , result ):
@@ -372,6 +377,15 @@ def _on_load_finished(self, ok):
372
377
This callback is called for all web_page.mainFrame()
373
378
loadFinished events.
374
379
"""
380
+ if self ._is_unsupported_content :
381
+ if self ._unsupported_content_reply .isRunning ():
382
+ # XXX: We'll come back later when download finishes
383
+ self .logger .log (
384
+ 'Still receving unsupported content' , min_level = 3 )
385
+ return
386
+ else :
387
+ self ._load_finished_after_unsupported_content_ready = True
388
+ self .logger .log ('Unsupported content received' , min_level = 3 )
375
389
if self .web_page .maybe_redirect (ok ):
376
390
self .logger .log ("Redirect or other non-fatal error detected" , min_level = 2 )
377
391
return
@@ -419,7 +433,11 @@ def _on_content_ready(self, ok, callback, errback, callback_id):
419
433
"""
420
434
This method is called when a QWebPage finishes loading its contents.
421
435
"""
422
- if self .web_page .maybe_redirect (ok ):
436
+ if self ._is_unsupported_content :
437
+ if self ._unsupported_content_reply .isRunning ():
438
+ # XXX: We'll come back later when download finishes
439
+ return
440
+ elif self .web_page .maybe_redirect (ok ):
423
441
# XXX: It assumes loadFinished will be called again because
424
442
# redirect happens. If redirect is detected improperly,
425
443
# loadFinished won't be called again, and Splash will return
@@ -431,6 +449,16 @@ def _on_content_ready(self, ok, callback, errback, callback_id):
431
449
432
450
if self .web_page .is_ok (ok ):
433
451
callback ()
452
+ elif self ._is_unsupported_content :
453
+ # XXX: Error downloading unsupported content.
454
+ # `self.web_page.error_info` shall be `None` now
455
+ error_info = RenderErrorInfo (
456
+ 'Network' ,
457
+ int (self ._unsupported_content_reply .error ()),
458
+ six .text_type (self ._unsupported_content_reply .errorString ()),
459
+ six .text_type (self ._unsupported_content_reply .url ().url ())
460
+ )
461
+ errback (error_info )
434
462
elif self .web_page .error_loading (ok ):
435
463
# XXX: maybe return a meaningful error page instead of generic
436
464
# error message?
@@ -505,6 +533,28 @@ def _on_url_changed(self, url):
505
533
self .web_page .har .store_redirect (six .text_type (url .toString ()))
506
534
self ._cancel_timers (self ._timers_to_cancel_on_redirect )
507
535
536
+ def _on_unsupported_content_finished (self ):
537
+ self .logger .log ('Unsupported content finished' , min_level = 3 )
538
+ if not self ._load_finished_after_unsupported_content_ready :
539
+ # XXX: The unsupported content reply might have finished before the
540
+ # original loadFinished signal emits. In such cases we do not want
541
+ # the same signal twice.
542
+ if not self ._unsupported_content_reply .error ():
543
+ self .web_page .mainFrame ().loadFinished .emit (True )
544
+ else :
545
+ self .web_page .mainFrame ().loadFinished .emit (False )
546
+
547
+ def _on_unsupported_content (self , reply ):
548
+ self .logger .log ('Unsupported content detected' , min_level = 3 )
549
+ self ._is_unsupported_content = True
550
+ self ._unsupported_content_reply = reply
551
+ if reply .isFinished ():
552
+ # Already finished. The content might be very short.
553
+ self .logger .log ('Unsupported content already finished' , min_level = 3 )
554
+ self ._on_unsupported_content_finished ()
555
+ else :
556
+ reply .finished .connect (self ._on_unsupported_content_finished )
557
+
508
558
def run_js_file (self , filename , handle_errors = True ):
509
559
"""
510
560
Load JS library from file ``filename`` to the current frame.
0 commit comments