21
21
from splash .qtutils import (OPERATION_QT_CONSTANTS , WrappedSignal , qt2py ,
22
22
qurl2ascii , to_qurl )
23
23
from splash .render_options import validate_size_str
24
- from splash .qwebpage import SplashQWebPage , SplashQWebView
24
+ from splash .qwebpage import SplashQWebPage , SplashQWebView , RenderErrorInfo
25
25
from splash .exceptions import JsError , OneShotCallbackError , ScriptError
26
26
from splash .utils import to_bytes
27
27
from splash .jsutils import (
@@ -71,6 +71,9 @@ def __init__(self, network_manager, splash_proxy_factory, verbosity,
71
71
self ._callback_proxies_to_cancel = weakref .WeakSet ()
72
72
self ._js_console = None
73
73
self ._autoload_scripts = []
74
+ self ._is_unsupported_content = False
75
+ self ._unsupported_content_reply = None
76
+ self ._load_finished_after_unsupported_content_ready = False
74
77
75
78
self .logger = _BrowserTabLogger (uid = self ._uid , verbosity = verbosity )
76
79
self ._init_webpage (verbosity , network_manager , splash_proxy_factory ,
@@ -140,6 +143,8 @@ def _setup_webpage_events(self):
140
143
self .web_page .mainFrame ().loadFinished .connect (self ._on_load_finished )
141
144
self .web_page .mainFrame ().urlChanged .connect (self ._on_url_changed )
142
145
self .web_page .mainFrame ().javaScriptWindowObjectCleared .connect (self ._on_javascript_window_object_cleared )
146
+ self .web_page .setForwardUnsupportedContent (True )
147
+ self .web_page .unsupportedContent .connect (self ._on_unsupported_content )
143
148
self .logger .add_web_page (self .web_page )
144
149
145
150
def return_result (self , result ):
@@ -379,6 +384,15 @@ def _on_load_finished(self, ok):
379
384
This callback is called for all web_page.mainFrame()
380
385
loadFinished events.
381
386
"""
387
+ if self ._is_unsupported_content :
388
+ if self ._unsupported_content_reply .isRunning ():
389
+ # XXX: We'll come back later when download finishes
390
+ self .logger .log (
391
+ 'Still receving unsupported content' , min_level = 3 )
392
+ return
393
+ else :
394
+ self ._load_finished_after_unsupported_content_ready = True
395
+ self .logger .log ('Unsupported content received' , min_level = 3 )
382
396
if self .web_page .maybe_redirect (ok ):
383
397
self .logger .log ("Redirect or other non-fatal error detected" , min_level = 2 )
384
398
return
@@ -426,7 +440,11 @@ def _on_content_ready(self, ok, callback, errback, callback_id):
426
440
"""
427
441
This method is called when a QWebPage finishes loading its contents.
428
442
"""
429
- if self .web_page .maybe_redirect (ok ):
443
+ if self ._is_unsupported_content :
444
+ if self ._unsupported_content_reply .isRunning ():
445
+ # XXX: We'll come back later when download finishes
446
+ return
447
+ elif self .web_page .maybe_redirect (ok ):
430
448
# XXX: It assumes loadFinished will be called again because
431
449
# redirect happens. If redirect is detected improperly,
432
450
# loadFinished won't be called again, and Splash will return
@@ -438,6 +456,16 @@ def _on_content_ready(self, ok, callback, errback, callback_id):
438
456
439
457
if self .web_page .is_ok (ok ):
440
458
callback ()
459
+ elif self ._is_unsupported_content :
460
+ # XXX: Error downloading unsupported content.
461
+ # `self.web_page.error_info` shall be `None` now
462
+ error_info = RenderErrorInfo (
463
+ 'Network' ,
464
+ int (self ._unsupported_content_reply .error ()),
465
+ six .text_type (self ._unsupported_content_reply .errorString ()),
466
+ six .text_type (self ._unsupported_content_reply .url ().url ())
467
+ )
468
+ errback (error_info )
441
469
elif self .web_page .error_loading (ok ):
442
470
# XXX: maybe return a meaningful error page instead of generic
443
471
# error message?
@@ -512,6 +540,28 @@ def _on_url_changed(self, url):
512
540
self .web_page .har .store_redirect (six .text_type (url .toString ()))
513
541
self ._cancel_timers (self ._timers_to_cancel_on_redirect )
514
542
543
+ def _on_unsupported_content_finished (self ):
544
+ self .logger .log ('Unsupported content finished' , min_level = 3 )
545
+ if not self ._load_finished_after_unsupported_content_ready :
546
+ # XXX: The unsupported content reply might have finished before the
547
+ # original loadFinished signal emits. In such cases we do not want
548
+ # the same signal twice.
549
+ if not self ._unsupported_content_reply .error ():
550
+ self .web_page .mainFrame ().loadFinished .emit (True )
551
+ else :
552
+ self .web_page .mainFrame ().loadFinished .emit (False )
553
+
554
+ def _on_unsupported_content (self , reply ):
555
+ self .logger .log ('Unsupported content detected' , min_level = 3 )
556
+ self ._is_unsupported_content = True
557
+ self ._unsupported_content_reply = reply
558
+ if reply .isFinished ():
559
+ # Already finished. The content might be very short.
560
+ self .logger .log ('Unsupported content already finished' , min_level = 3 )
561
+ self ._on_unsupported_content_finished ()
562
+ else :
563
+ reply .finished .connect (self ._on_unsupported_content_finished )
564
+
515
565
def run_js_file (self , filename , handle_errors = True ):
516
566
"""
517
567
Load JS library from file ``filename`` to the current frame.
0 commit comments