Ejemplo n.º 1
0
    def __init__(self, framework, mainWindow):
        QObject.__init__(self, mainWindow)
        self.framework = framework
        QObject.connect(self, SIGNAL('destroyed(QObject*)'), self._destroyed)
        self.mainWindow = mainWindow
        self.cjInteractor = TesterTab.ClickJackingInteractor(self)
        self.cjTester = ClickjackingTester(self.framework)

        self.scintillaWidgets = set(
        )  # store scintilla widget reference to handle zoom in/zoom out

        #        self.networkAccessManager = StandardNetworkAccessManager(self.framework, self.framework.get_global_cookie_jar())
        self.pageFactory = TesterPageFactory(self.framework, self.cjInteractor,
                                             None, self)

        self.framework.subscribe_populate_tester_csrf(
            self.tester_populate_csrf)
        self.framework.subscribe_populate_tester_click_jacking(
            self.tester_populate_click_jacking)

        self.Data = None
        self.cursor = None
        self.framework.subscribe_database_events(self.db_attach,
                                                 self.db_detach)

        self.setScintillaProperties(self.mainWindow.csrfGenEdit)
        self.mainWindow.testerRegenBtn.clicked.connect(self.regen_csrf)
        self.mainWindow.csrfOpenBtn.clicked.connect(
            self.handle_csrfOpenBtn_clicked)

        self.setScintillaProperties(self.mainWindow.testerClickjackingEditHtml)
        self.mainWindow.testerClickjackingSimulateButton.clicked.connect(
            self.handle_testerClickjackingSimulateButton_clicked)
        self.mainWindow.testerClickjackingOpenInBrowserButton.clicked.connect(
            self.handle_testerClickjackingOpenInBrowserButton_clicked)
        self.mainWindow.testerClickjackingGenerateButton.clicked.connect(
            self.handle_testerClickjackingGenerateButton_clicked)
        self.mainWindow.testerClickjackingEnableJavascript.clicked.connect(
            self.handle_testerClickjackingEnableJavascript_clicked)

        self.clickjackingRenderWebView = RenderingWebView(
            self.framework, self.pageFactory,
            self.mainWindow.testerClickjackingEmbeddedBrowserPlaceholder)
        self.clickjackingRenderWebView.loadFinished.connect(
            self.handle_clickjackingRenderWebView_loadFinished)
        self.clickjackingRenderWebView.urlChanged.connect(
            self.handle_clickjackingRenderWebView_urlChanged)
        self.clickjackingRenderWebView.titleChanged.connect(
            self.handle_clickjackingRenderWebView_titleChanged)

        self.framework.subscribe_zoom_in(self.zoom_in_scintilla)
        self.framework.subscribe_zoom_out(self.zoom_out_scintilla)
Ejemplo n.º 2
0
    def __init__(self, framework, mainWindow):
        QObject.__init__(self, mainWindow)
        self.framework = framework
        QObject.connect(self, SIGNAL("destroyed(QObject*)"), self._destroyed)
        self.mainWindow = mainWindow
        self.cjInteractor = TesterTab.ClickJackingInteractor(self)
        self.cjTester = ClickjackingTester(self.framework)

        self.scintillaWidgets = set()  # store scintilla widget reference to handle zoom in/zoom out

        #        self.networkAccessManager = StandardNetworkAccessManager(self.framework, self.framework.get_global_cookie_jar())
        self.pageFactory = TesterPageFactory(self.framework, self.cjInteractor, None, self)

        self.framework.subscribe_populate_tester_csrf(self.tester_populate_csrf)
        self.framework.subscribe_populate_tester_click_jacking(self.tester_populate_click_jacking)

        self.Data = None
        self.cursor = None
        self.framework.subscribe_database_events(self.db_attach, self.db_detach)

        self.setScintillaProperties(self.mainWindow.csrfGenEdit)
        self.mainWindow.testerRegenBtn.clicked.connect(self.regen_csrf)
        self.mainWindow.csrfOpenBtn.clicked.connect(self.handle_csrfOpenBtn_clicked)

        self.setScintillaProperties(self.mainWindow.testerClickjackingEditHtml)
        self.mainWindow.testerClickjackingSimulateButton.clicked.connect(
            self.handle_testerClickjackingSimulateButton_clicked
        )
        self.mainWindow.testerClickjackingOpenInBrowserButton.clicked.connect(
            self.handle_testerClickjackingOpenInBrowserButton_clicked
        )
        self.mainWindow.testerClickjackingGenerateButton.clicked.connect(
            self.handle_testerClickjackingGenerateButton_clicked
        )
        self.mainWindow.testerClickjackingEnableJavascript.clicked.connect(
            self.handle_testerClickjackingEnableJavascript_clicked
        )

        self.clickjackingRenderWebView = RenderingWebView(
            self.framework, self.pageFactory, self.mainWindow.testerClickjackingEmbeddedBrowserPlaceholder
        )
        self.clickjackingRenderWebView.loadFinished.connect(self.handle_clickjackingRenderWebView_loadFinished)
        self.clickjackingRenderWebView.urlChanged.connect(self.handle_clickjackingRenderWebView_urlChanged)
        self.clickjackingRenderWebView.titleChanged.connect(self.handle_clickjackingRenderWebView_titleChanged)

        self.framework.subscribe_zoom_in(self.zoom_in_scintilla)
        self.framework.subscribe_zoom_out(self.zoom_out_scintilla)
Ejemplo n.º 3
0
class TesterTab(QObject):
    class ClickJackingInteractor:
        def __init__(self, parent):
            self.parent = parent

        def log(self, logtype, logmessage):
            self.parent.clickjacking_console_log(logtype, logmessage)

        def confirm(self, frame, msg):
            return self.parent.clickjacking_browser_confirm(frame, msg)

    DEFAULT_FRAMED_URL = "http://attacker.example.com/framed.html"
    DEFAULT_CSRF_URL = "http://attacker.example.com/csrf.html"

    def __init__(self, framework, mainWindow):
        QObject.__init__(self, mainWindow)
        self.framework = framework
        QObject.connect(self, SIGNAL("destroyed(QObject*)"), self._destroyed)
        self.mainWindow = mainWindow
        self.cjInteractor = TesterTab.ClickJackingInteractor(self)
        self.cjTester = ClickjackingTester(self.framework)

        self.scintillaWidgets = set()  # store scintilla widget reference to handle zoom in/zoom out

        #        self.networkAccessManager = StandardNetworkAccessManager(self.framework, self.framework.get_global_cookie_jar())
        self.pageFactory = TesterPageFactory(self.framework, self.cjInteractor, None, self)

        self.framework.subscribe_populate_tester_csrf(self.tester_populate_csrf)
        self.framework.subscribe_populate_tester_click_jacking(self.tester_populate_click_jacking)

        self.Data = None
        self.cursor = None
        self.framework.subscribe_database_events(self.db_attach, self.db_detach)

        self.setScintillaProperties(self.mainWindow.csrfGenEdit)
        self.mainWindow.testerRegenBtn.clicked.connect(self.regen_csrf)
        self.mainWindow.csrfOpenBtn.clicked.connect(self.handle_csrfOpenBtn_clicked)

        self.setScintillaProperties(self.mainWindow.testerClickjackingEditHtml)
        self.mainWindow.testerClickjackingSimulateButton.clicked.connect(
            self.handle_testerClickjackingSimulateButton_clicked
        )
        self.mainWindow.testerClickjackingOpenInBrowserButton.clicked.connect(
            self.handle_testerClickjackingOpenInBrowserButton_clicked
        )
        self.mainWindow.testerClickjackingGenerateButton.clicked.connect(
            self.handle_testerClickjackingGenerateButton_clicked
        )
        self.mainWindow.testerClickjackingEnableJavascript.clicked.connect(
            self.handle_testerClickjackingEnableJavascript_clicked
        )

        self.clickjackingRenderWebView = RenderingWebView(
            self.framework, self.pageFactory, self.mainWindow.testerClickjackingEmbeddedBrowserPlaceholder
        )
        self.clickjackingRenderWebView.loadFinished.connect(self.handle_clickjackingRenderWebView_loadFinished)
        self.clickjackingRenderWebView.urlChanged.connect(self.handle_clickjackingRenderWebView_urlChanged)
        self.clickjackingRenderWebView.titleChanged.connect(self.handle_clickjackingRenderWebView_titleChanged)

        self.framework.subscribe_zoom_in(self.zoom_in_scintilla)
        self.framework.subscribe_zoom_out(self.zoom_out_scintilla)

    def _destroyed(self):
        self.framework.unsubscribe_zoom_in(self.zoom_in_scintilla)
        self.framework.unsubscribe_zoom_out(self.zoom_out_scintilla)

    def db_attach(self):
        self.Data = self.framework.getDB()
        self.cursor = self.Data.allocate_thread_cursor()

    def db_detach(self):
        self.close_cursor()
        self.Data = None

    def close_cursor(self):
        if self.cursor and self.Data:
            self.cursor.close()
            self.Data.release_thread_cursor(self.cursor)
            self.cursor = None

    def tester_populate_csrf(self, response_id):

        row = self.Data.read_responses_by_id(self.cursor, response_id)

        if not row:
            return

        responseItems = interface.data_row_to_response_items(row)

        url = responseItems[ResponsesTable.URL]
        # Are reqHeaders necessary?
        reqHeaders = str(responseItems[ResponsesTable.REQ_HEADERS], "utf-8", "ignore")
        reqData = str(responseItems[ResponsesTable.REQ_DATA], "utf-8", "ignore")  # TODO: consider replacement

        data = reqHeaders + "\n" + reqData

        # Check to ensure that either a GET or a POST is being used and pass that along to the function
        # check = re.compile("^(GET|POST)", re.I)
        # result = check.match(reqHeaders)
        # if not result:
        #    return()

        GET = re.compile("^GET", re.I)
        POST = re.compile("^POST", re.I)

        if GET.match(reqHeaders):
            htmlresult = CSRFTester.generate_csrf_html(url, reqData, "get")
        elif POST.match(reqHeaders):
            htmlresult = CSRFTester.generate_csrf_html(url, reqData, "post")
        else:
            return ()

        # htmlresult = CSRFTester.generate_csrf_html(url, reqData)

        self.mainWindow.testerCSRFURLEdit.setText(url)
        self.mainWindow.csrfGenEdit.setText(htmlresult)
        self.mainWindow.csrfReqEdit.setPlainText(data)

    def regen_csrf(self):
        # Regenerate CSRF playload based on selection
        if self.mainWindow.testerImgGen.isChecked():
            url = self.mainWindow.testerCSRFURLEdit.text()
            htmlresult = CSRFTester.generate_csrf_img(url, self.mainWindow.csrfGenEdit.text())
            self.mainWindow.csrfGenEdit.setText(htmlresult)

    def handle_csrfOpenBtn_clicked(self):
        url = self.DEFAULT_CSRF_URL  # TODO: exposed this (?)
        body = self.mainWindow.csrfGenEdit.text()
        content_type = "text/html"
        self.framework.open_content_in_browser(url, body, content_type)

    def tester_populate_click_jacking(self, response_id):
        row = self.Data.read_responses_by_id(self.cursor, response_id)
        if not row:
            return
        responseItems = interface.data_row_to_response_items(row)
        url = responseItems[ResponsesTable.URL]
        self.setup_clickjacking_url(url)

    def setup_clickjacking_url(self, url):
        self._clickjacking_simulation_running = False
        self.mainWindow.testerClickjackingUrlEdit.setText("")
        self.mainWindow.testerClickjackingConsoleLogTextEdit.setText("")
        self.clickjackingRenderWebView.setHtml("", QUrl("about:blank"))

        htmlcontent = self.cjTester.make_default_frame_html(url)
        self.mainWindow.testerClickjackingTargetURL.setText(url)
        self.mainWindow.testerClickjackingEditHtml.setText(htmlcontent)

    def handle_testerClickjackingSimulateButton_clicked(self):
        self.mainWindow.testerClickjackingConsoleLogTextEdit.setText("Starting Clickjacking Simulation")
        self.clickjackingRenderWebView.page().set_javascript_enabled(
            self.mainWindow.testerClickjackingEnableJavascript.isChecked()
        )
        self._clickjacking_simulation_running = True
        url = self.mainWindow.testerClickjackingUrlEdit.text()
        # TODO: better way than to force unique URL to reload content ?
        if "?" in url:
            url = url[0 : url.find("?") + 1] + uuid.uuid4().hex
        else:
            url = url + "?" + uuid.uuid4().hex
        headers = ""
        body = self.mainWindow.testerClickjackingEditHtml.text()
        content_type = "text/html"
        self.clickjackingRenderWebView.fill_from_response(url, headers, body, content_type)

    def handle_testerClickjackingGenerateButton_clicked(self):
        entry = self.mainWindow.testerClickjackingTargetURL.text()
        url = QUrl.fromUserInput(entry).toEncoded().data().decode("utf-8")
        self.setup_clickjacking_url(url)

    def handle_testerClickjackingOpenInBrowserButton_clicked(self):
        url = self.clickjackingRenderWebView.url().toEncoded().data().decode("utf-8")
        body = self.mainWindow.testerClickjackingEditHtml.text()
        content_type = "text/html"
        self.framework.open_content_in_browser(url, body, content_type)

    def handle_clickjackingRenderWebView_loadFinished(self):
        self.clickjacking_console_log("info", "Page load finished")
        if not self._clickjacking_simulation_running:
            self.mainWindow.testerClickjackingConsoleLogTextEdit.setPlainText("")

    def handle_clickjackingRenderWebView_urlChanged(self):
        url = self.clickjackingRenderWebView.url().toEncoded().data().decode("utf-8")
        if "about:blank" == url and not self._clickjacking_simulation_running:
            self.mainWindow.testerClickjackingUrlEdit.setText(self.DEFAULT_FRAMED_URL)
        else:
            self.mainWindow.testerClickjackingUrlEdit.setText(url)

    def handle_testerClickjackingEnableJavascript_clicked(self):
        self.clickjackingRenderWebView.page().set_javascript_enabled(
            self.mainWindow.testerClickjackingEnableJavascript.isChecked()
        )

    def handle_clickjackingRenderWebView_titleChanged(self, title):
        self.clickjacking_console_log("info", "Page title changed to [%s]" % (title))

    def clickjacking_browser_confirm(self, frame, msg):
        if not self._clickjacking_simulation_running:
            return True
        if "Clickjacking: Navigate Away" == msg:  # TODO: create a common location for this string
            if self.mainWindow.testerClickjackingIgnoreNavigationRequests.isChecked():
                self.clickjacking_console_log(
                    "info", "Simulating canceled navigation response to confirmation: %s" % (msg)
                )
                return False
        return True

    def clickjacking_console_log(self, logtype, logmessage):
        msg = None
        if "javaScriptConsoleMessage" == logtype:
            (lineNumber, sourceID, message) = logmessage
            msg = "console log from [%s / %s]: %s" % (lineNumber, sourceID, message)
        elif "info":
            msg = logmessage

        if msg:
            curtext = self.mainWindow.testerClickjackingConsoleLogTextEdit.toPlainText()
            curtext += "\n" + msg
            self.mainWindow.testerClickjackingConsoleLogTextEdit.setPlainText(curtext)

    # TODO: refactor into common module in framework
    def setScintillaProperties(self, scintillaWidget, contentType="html"):
        scintillaWidget.setFont(self.framework.get_font())
        scintillaWidget.setWrapMode(1)
        scintillaWidget.zoomTo(self.framework.get_zoom_size())
        # TOOD: set based on line numbers (size is in pixels)
        scintillaWidget.setMarginWidth(1, "1000")
        lexerInstance = Qsci.QsciLexerHTML(scintillaWidget)
        lexerInstance.setFont(self.framework.get_font())
        scintillaWidget.setLexer(lexerInstance)
        self.scintillaWidgets.add(scintillaWidget)

    def zoom_in_scintilla(self):
        for scintillaWidget in self.scintillaWidgets:
            scintillaWidget.zoomIn()

    def zoom_out_scintilla(self):
        for scintillaWidget in self.scintillaWidgets:
            scintillaWidget.zoomOut()
Ejemplo n.º 4
0
class TesterTab(QObject):
    class ClickJackingInteractor():
        def __init__(self, parent):
            self.parent = parent

        def log(self, logtype, logmessage):
            self.parent.clickjacking_console_log(logtype, logmessage)

        def confirm(self, frame, msg):
            return self.parent.clickjacking_browser_confirm(frame, msg)

    DEFAULT_FRAMED_URL = 'http://attacker.example.com/framed.html'
    DEFAULT_CSRF_URL = 'http://attacker.example.com/csrf.html'

    def __init__(self, framework, mainWindow):
        QObject.__init__(self, mainWindow)
        self.framework = framework
        QObject.connect(self, SIGNAL('destroyed(QObject*)'), self._destroyed)
        self.mainWindow = mainWindow
        self.cjInteractor = TesterTab.ClickJackingInteractor(self)
        self.cjTester = ClickjackingTester(self.framework)

        self.scintillaWidgets = set(
        )  # store scintilla widget reference to handle zoom in/zoom out

        #        self.networkAccessManager = StandardNetworkAccessManager(self.framework, self.framework.get_global_cookie_jar())
        self.pageFactory = TesterPageFactory(self.framework, self.cjInteractor,
                                             None, self)

        self.framework.subscribe_populate_tester_csrf(
            self.tester_populate_csrf)
        self.framework.subscribe_populate_tester_click_jacking(
            self.tester_populate_click_jacking)

        self.Data = None
        self.cursor = None
        self.framework.subscribe_database_events(self.db_attach,
                                                 self.db_detach)

        self.setScintillaProperties(self.mainWindow.csrfGenEdit)
        self.mainWindow.testerRegenBtn.clicked.connect(self.regen_csrf)
        self.mainWindow.csrfOpenBtn.clicked.connect(
            self.handle_csrfOpenBtn_clicked)

        self.setScintillaProperties(self.mainWindow.testerClickjackingEditHtml)
        self.mainWindow.testerClickjackingSimulateButton.clicked.connect(
            self.handle_testerClickjackingSimulateButton_clicked)
        self.mainWindow.testerClickjackingOpenInBrowserButton.clicked.connect(
            self.handle_testerClickjackingOpenInBrowserButton_clicked)
        self.mainWindow.testerClickjackingGenerateButton.clicked.connect(
            self.handle_testerClickjackingGenerateButton_clicked)
        self.mainWindow.testerClickjackingEnableJavascript.clicked.connect(
            self.handle_testerClickjackingEnableJavascript_clicked)

        self.clickjackingRenderWebView = RenderingWebView(
            self.framework, self.pageFactory,
            self.mainWindow.testerClickjackingEmbeddedBrowserPlaceholder)
        self.clickjackingRenderWebView.loadFinished.connect(
            self.handle_clickjackingRenderWebView_loadFinished)
        self.clickjackingRenderWebView.urlChanged.connect(
            self.handle_clickjackingRenderWebView_urlChanged)
        self.clickjackingRenderWebView.titleChanged.connect(
            self.handle_clickjackingRenderWebView_titleChanged)

        self.framework.subscribe_zoom_in(self.zoom_in_scintilla)
        self.framework.subscribe_zoom_out(self.zoom_out_scintilla)

    def _destroyed(self):
        self.framework.unsubscribe_zoom_in(self.zoom_in_scintilla)
        self.framework.unsubscribe_zoom_out(self.zoom_out_scintilla)

    def db_attach(self):
        self.Data = self.framework.getDB()
        self.cursor = self.Data.allocate_thread_cursor()

    def db_detach(self):
        self.close_cursor()
        self.Data = None

    def close_cursor(self):
        if self.cursor and self.Data:
            self.cursor.close()
            self.Data.release_thread_cursor(self.cursor)
            self.cursor = None

    def tester_populate_csrf(self, response_id):

        row = self.Data.read_responses_by_id(self.cursor, response_id)

        if not row:
            return

        responseItems = interface.data_row_to_response_items(row)

        url = responseItems[ResponsesTable.URL]
        # Are reqHeaders necessary?
        reqHeaders = str(responseItems[ResponsesTable.REQ_HEADERS], 'utf-8',
                         'ignore')
        reqData = str(responseItems[ResponsesTable.REQ_DATA], 'utf-8',
                      'ignore')  # TODO: consider replacement

        data = reqHeaders + "\n" + reqData

        # Check to ensure that either a GET or a POST is being used and pass that along to the function
        # check = re.compile("^(GET|POST)", re.I)
        # result = check.match(reqHeaders)
        # if not result:
        #    return()

        GET = re.compile("^GET", re.I)
        POST = re.compile("^POST", re.I)

        if GET.match(reqHeaders):
            htmlresult = CSRFTester.generate_csrf_html(url, reqData, "get")
        elif POST.match(reqHeaders):
            htmlresult = CSRFTester.generate_csrf_html(url, reqData, "post")
        else:
            return ()

        # htmlresult = CSRFTester.generate_csrf_html(url, reqData)

        self.mainWindow.testerCSRFURLEdit.setText(url)
        self.mainWindow.csrfGenEdit.setText(htmlresult)
        self.mainWindow.csrfReqEdit.setPlainText(data)

    def regen_csrf(self):
        # Regenerate CSRF playload based on selection
        if self.mainWindow.testerImgGen.isChecked():
            url = self.mainWindow.testerCSRFURLEdit.text()
            htmlresult = CSRFTester.generate_csrf_img(
                url, self.mainWindow.csrfGenEdit.text())
            self.mainWindow.csrfGenEdit.setText(htmlresult)

    def handle_csrfOpenBtn_clicked(self):
        url = self.DEFAULT_CSRF_URL  # TODO: exposed this (?)
        body = self.mainWindow.csrfGenEdit.text()
        content_type = 'text/html'
        self.framework.open_content_in_browser(url, body, content_type)

    def tester_populate_click_jacking(self, response_id):
        row = self.Data.read_responses_by_id(self.cursor, response_id)
        if not row:
            return
        responseItems = interface.data_row_to_response_items(row)
        url = responseItems[ResponsesTable.URL]
        self.setup_clickjacking_url(url)

    def setup_clickjacking_url(self, url):
        self._clickjacking_simulation_running = False
        self.mainWindow.testerClickjackingUrlEdit.setText('')
        self.mainWindow.testerClickjackingConsoleLogTextEdit.setText('')
        self.clickjackingRenderWebView.setHtml('', QUrl('about:blank'))

        htmlcontent = self.cjTester.make_default_frame_html(url)
        self.mainWindow.testerClickjackingTargetURL.setText(url)
        self.mainWindow.testerClickjackingEditHtml.setText(htmlcontent)

    def handle_testerClickjackingSimulateButton_clicked(self):
        self.mainWindow.testerClickjackingConsoleLogTextEdit.setText(
            'Starting Clickjacking Simulation')
        self.clickjackingRenderWebView.page().set_javascript_enabled(
            self.mainWindow.testerClickjackingEnableJavascript.isChecked())
        self._clickjacking_simulation_running = True
        url = self.mainWindow.testerClickjackingUrlEdit.text()
        # TODO: better way than to force unique URL to reload content ?
        if '?' in url:
            url = url[0:url.find('?') + 1] + uuid.uuid4().hex
        else:
            url = url + '?' + uuid.uuid4().hex
        headers = ''
        body = self.mainWindow.testerClickjackingEditHtml.text()
        content_type = 'text/html'
        self.clickjackingRenderWebView.fill_from_response(
            url, headers, body, content_type)

    def handle_testerClickjackingGenerateButton_clicked(self):
        entry = self.mainWindow.testerClickjackingTargetURL.text()
        url = QUrl.fromUserInput(entry).toEncoded().data().decode('utf-8')
        self.setup_clickjacking_url(url)

    def handle_testerClickjackingOpenInBrowserButton_clicked(self):
        url = self.clickjackingRenderWebView.url().toEncoded().data().decode(
            'utf-8')
        body = self.mainWindow.testerClickjackingEditHtml.text()
        content_type = 'text/html'
        self.framework.open_content_in_browser(url, body, content_type)

    def handle_clickjackingRenderWebView_loadFinished(self):
        self.clickjacking_console_log('info', 'Page load finished')
        if not self._clickjacking_simulation_running:
            self.mainWindow.testerClickjackingConsoleLogTextEdit.setPlainText(
                '')

    def handle_clickjackingRenderWebView_urlChanged(self):
        url = self.clickjackingRenderWebView.url().toEncoded().data().decode(
            'utf-8')
        if 'about:blank' == url and not self._clickjacking_simulation_running:
            self.mainWindow.testerClickjackingUrlEdit.setText(
                self.DEFAULT_FRAMED_URL)
        else:
            self.mainWindow.testerClickjackingUrlEdit.setText(url)

    def handle_testerClickjackingEnableJavascript_clicked(self):
        self.clickjackingRenderWebView.page().set_javascript_enabled(
            self.mainWindow.testerClickjackingEnableJavascript.isChecked())

    def handle_clickjackingRenderWebView_titleChanged(self, title):
        self.clickjacking_console_log('info',
                                      'Page title changed to [%s]' % (title))

    def clickjacking_browser_confirm(self, frame, msg):
        if not self._clickjacking_simulation_running:
            return True
        if 'Clickjacking: Navigate Away' == msg:  # TODO: create a common location for this string
            if self.mainWindow.testerClickjackingIgnoreNavigationRequests.isChecked(
            ):
                self.clickjacking_console_log(
                    'info',
                    'Simulating canceled navigation response to confirmation: %s'
                    % (msg))
                return False
        return True

    def clickjacking_console_log(self, logtype, logmessage):
        msg = None
        if 'javaScriptConsoleMessage' == logtype:
            (lineNumber, sourceID, message) = logmessage
            msg = 'console log from [%s / %s]: %s' % (lineNumber, sourceID,
                                                      message)
        elif 'info':
            msg = logmessage

        if msg:
            curtext = self.mainWindow.testerClickjackingConsoleLogTextEdit.toPlainText(
            )
            curtext += '\n' + msg
            self.mainWindow.testerClickjackingConsoleLogTextEdit.setPlainText(
                curtext)

    # TODO: refactor into common module in framework
    def setScintillaProperties(self, scintillaWidget, contentType='html'):
        scintillaWidget.setFont(self.framework.get_font())
        scintillaWidget.setWrapMode(1)
        scintillaWidget.zoomTo(self.framework.get_zoom_size())
        # TOOD: set based on line numbers (size is in pixels)
        scintillaWidget.setMarginWidth(1, '1000')
        lexerInstance = Qsci.QsciLexerHTML(scintillaWidget)
        lexerInstance.setFont(self.framework.get_font())
        scintillaWidget.setLexer(lexerInstance)
        self.scintillaWidgets.add(scintillaWidget)

    def zoom_in_scintilla(self):
        for scintillaWidget in self.scintillaWidgets:
            scintillaWidget.zoomIn()

    def zoom_out_scintilla(self):
        for scintillaWidget in self.scintillaWidgets:
            scintillaWidget.zoomOut()