예제 #1
0
    def setUrl(self, url):
        """ Reimplemented to make sure that when we return, the DOM is ready to
        use.

        Based on the local event loop approach described here:
        http://doc.qt.digia.com/qq/qq27-responsive-guis.html#waitinginalocaleventloop
        """
        event_loop = QtCore.QEventLoop()
        self._loaded = False

        def on_load():
            self._loaded = True
            event_loop.quit()

        self._page.loadFinished.connect(on_load)

        super(ProxyQWebView, self).setUrl(QtCore.QUrl(url))

        if not self._loaded:
            event_loop.exec_()
예제 #2
0
class ProxyQWebPage(QtWebKit.QWebPage):
    """ Overridden to open external links in a web browser.

    Source: http://www.expobrain.net/2012/03/01/open-urls-in-external-browser-by-javascript-in-webkit/
    """

    def acceptNavigationRequest(self, frame, request, type):
        # Checking this is same as checking if the client side <a> tag making
        # the HTTP request had target="_blank" as an attribute.
        if frame is None:
            import webbrowser
            webbrowser.open_new(request.url().toString())

            return False

        else:
            return super(ProxyQWebPage, self).acceptNavigationRequest(
                frame, request, type
            )

    def createWindow(self, *args, **kwargs):
        return ProxyQWebPage()

if __name__ == '__main__':
    app = QtGui.QApplication([])
    w = ProxyQWebView()
    w.show()
    w.raise_()
    w.load(QtCore.QUrl('http://www.google.com/'))
    app.exec_()
예제 #3
0
class ProxyReplyWorker(QtCore.QThread):
    """ Worker thread to fetch urls for QNetworkProxy. """

    # Signals to forward to ProxyReply
    metaDataChanged = QtCore.Signal()
    readyRead = QtCore.Signal()
    finished = QtCore.Signal()

    OPERATIONS = {QtNetwork.QNetworkAccessManager.GetOperation: 'GET',
                  QtNetwork.QNetworkAccessManager.PostOperation: 'POST',}

    def __init__(self, reply, parent=None):
        super(ProxyReplyWorker, self).__init__(parent)
        self.reply = reply
        self.metaDataChanged.connect(self.reply.metaDataChanged)
        self.readyRead.connect(self.reply.readyRead)
        self.finished.connect(self.reply.finished)

    ###########################################################################
    # QThread interface.
    ###########################################################################

    def run(self):
        """ handles the request by acting as a WSGI forwarding server. """
        reply = self.reply
        url = reply.url()
        req = reply.request()

        # WSGI environ variables
        env = {
            'REQUEST_METHOD': self.OPERATIONS[reply.operation()],
            'SCRIPT_NAME': '',
            'PATH_INFO': url.path(),
            'SERVER_NAME': url.host(),
            'SERVER_PORT': '80',
            'SERVER_PROTOCOL': 'HTTP/1.1',
            'QUERY_STRING': str(url.encodedQuery()),
            'wsgi.version': (1, 0),
            'wsgi.url_scheme': url.scheme(),
            'wsgi.input': StringIO(reply.req_data),
            'wsgi.errors': sys.stderr,
            'wsgi.multithread': False,
            'wsgi.multiprocess': True,
            'wsgi.run_once': False,
        }

        # Set WSGI HTTP request headers
        for head_name in req.rawHeaderList():
            env_name = 'HTTP_' + head_name.data().replace('-','_').upper()
            head_val = req.rawHeader(head_name)
            env[env_name] = head_val.data()

        try:
            local_buf = []
            local_buf_len = 0
            for read in reply.handler(env, self._start_response):
                if reply.aborted:
                    return
                local_buf.append(str(read))
                local_buf_len += len(read)
                if local_buf_len >= 8192:
                    # Do not write to buffer on every read, app is slowed down
                    # due to lock contention
                    with reply._buflock:
                        reply.buffer += ''.join(local_buf)
                    local_buf = []
                    local_buf_len = 0
                    self.readyRead.emit()
            with reply._buflock:
                reply.buffer += ''.join(local_buf)

        except Exception as e:
            if reply.aborted:
                return
            reply.setAttribute(
                QtNetwork.QNetworkRequest.HttpStatusCodeAttribute, 500
            )
            reply.setAttribute(
                QtNetwork.QNetworkRequest.HttpReasonPhraseAttribute,
                'Internal Error'
            )
            with reply._buflock:
                reply.buffer += 'WSGI Proxy "Server" Error.\n' + str(e)
        finally:
            self.readyRead.emit()
            self.finished.emit()

    ###########################################################################
    # Private interface.
    ###########################################################################

    def _start_response(self, status, response_headers):
        """ WSGI start_response callable. """
        code, reason = status.split(' ', 1)
        self.reply.setAttribute(
            QtNetwork.QNetworkRequest.HttpStatusCodeAttribute, int(code)
        )
        self.reply.setAttribute(
            QtNetwork.QNetworkRequest.HttpReasonPhraseAttribute, reason
        )
        for name, value in response_headers:
            self.reply.setRawHeader(name, str(value))

        self.metaDataChanged.emit()