From e6866f7d85ef985366791f1c1fc3017d6b59aa60 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 17 Jun 2014 15:28:41 +0200 Subject: [PATCH] Don't go to insert mode on disabled/readonly fields --- qutebrowser/test/utils/test_webelem.py | 34 +++++++++++++++++++++++--- qutebrowser/utils/webelem.py | 9 +++++++ qutebrowser/widgets/webview.py | 4 +-- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/qutebrowser/test/utils/test_webelem.py b/qutebrowser/test/utils/test_webelem.py index d4df78114..f86066bc9 100644 --- a/qutebrowser/test/utils/test_webelem.py +++ b/qutebrowser/test/utils/test_webelem.py @@ -34,7 +34,7 @@ class FakeWebElement: """A stub for QWebElement.""" def __init__(self, geometry=None, frame=None, null=False, visibility='', - display=''): + display='', attributes=None): """Constructor. Args: @@ -43,18 +43,17 @@ class FakeWebElement: null: Whether the element is null or not. visibility: The CSS visibility style property calue. display: The CSS display style property calue. + attributes: Boolean HTML attributes to be added. Raise: ValueError if element is not null and geometry/frame are not given. """ - if (not null) and (geometry is None or frame is None): - raise ValueError("geometry and frame have to be set if element " - "is not null!") self.geometry = Mock(return_value=geometry) self.webFrame = Mock(return_value=frame) self.isNull = Mock(return_value=null) self._visibility = visibility self._display = display + self._attributes = attributes def styleProperty(self, name, strategy): """Return the CSS style property named name. @@ -76,6 +75,13 @@ class FakeWebElement: raise ValueError("styleProperty called with unknown name " "'{}'".format(name)) + def hasAttribute(self, name): + """Check if the element has an attribute named name.""" + if self._attributes is None: + return False + else: + return name in self._attributes + class FakeWebFrame: @@ -282,6 +288,26 @@ class IsVisibleIframeTests(TestCase): self.assertTrue(webelem.is_visible(self.elem4, self.frame)) +class IsWritableTests(TestCase): + + """Check is_writable.""" + + def test_writable(self): + """Test a normal element.""" + elem = FakeWebElement() + self.assertTrue(webelem.is_writable(elem)) + + def test_disabled(self): + """Test a disabled element.""" + elem = FakeWebElement(attributes=['disabled']) + self.assertFalse(webelem.is_writable(elem)) + + def test_readonly(self): + """Test a readonly element.""" + elem = FakeWebElement(attributes=['readonly']) + self.assertFalse(webelem.is_writable(elem)) + + class JavascriptEscapeTests(TestCase): """Check javascript_escape. diff --git a/qutebrowser/utils/webelem.py b/qutebrowser/utils/webelem.py index eba800329..3830b3263 100644 --- a/qutebrowser/utils/webelem.py +++ b/qutebrowser/utils/webelem.py @@ -119,6 +119,15 @@ def rect_on_view(elem): return rect +def is_writable(elem): + """Check wheter an element is writable. + + Args: + elem: The QWebElement to check. + """ + return not (elem.hasAttribute('disabled') or elem.hasAttribute('readonly')) + + def javascript_escape(text): """Escape values special to javascript in strings. diff --git a/qutebrowser/widgets/webview.py b/qutebrowser/widgets/webview.py index 4045d97c6..decce1b84 100644 --- a/qutebrowser/widgets/webview.py +++ b/qutebrowser/widgets/webview.py @@ -184,12 +184,12 @@ class WebView(QWebView): hitresult: A QWebHitTestResult """ # FIXME is this algorithm accurate? - if hitresult.isContentEditable(): + elem = hitresult.element() + if hitresult.isContentEditable() and webelem.is_writable(elem): # text fields and the like return True if not config.get('input', 'insert-mode-on-plugins'): return False - elem = hitresult.element() tag = elem.tagName().lower() if tag in ('embed', 'applet', 'select'): # Flash/Java/...