Greasemonkey: Add test for window scoping refinements.

Adds a test to codify what I think greasemonkey scripts expect from
their scope chains. Particularly that they can:

1. access the global `window` object
2. access all of the attributes of the global window object as global
   objects themselves
3. see any changes the page made to the global scope
4. write to attributes of `window` and have those attributes, and changes
   to existing attributes, accessable via global scope
5. do number 4 without breaking the pages expectations, that is what
   `unsafeWindow` is for

There are some other points about greasemonkey scripts' environment that
I believe to be true but am not testing in this change:

* changes a page makes to `window` _after_ a greasemonkey script is
  injected will still be visible to the script if it cares to check and
  it hasn't already shadowed them
* said changes will not overwrite changes that the greasemonkey script
  has made.
This commit is contained in:
Jimmy 2018-04-22 17:51:50 +12:00
parent 23bfe6daa2
commit c7a9792b67

View File

@ -158,3 +158,62 @@ def test_required_scripts_are_included(download_stub, tmpdir):
# Additionally check that the base script is still being parsed correctly
assert "Script is running." in scripts[0].code()
assert scripts[0].excludes
class TestWindowIsolation:
"""Check that greasemonkey scripts get a shadowed global scope."""
@classmethod
def setup_class(cls):
# Change something in the global scope
cls.setup_script = "window.$ = 'global'"
# Greasemonkey script to report back on its scope.
test_script = greasemonkey.GreasemonkeyScript.parse(
textwrap.dedent("""
// ==UserScript==
// @name scopetest
// ==/UserScript==
// Check the thing the page set is set to the expected type
result.push(window.$);
result.push($);
// Now overwrite it
window.$ = 'shadowed';
// And check everything is how the script would expect it to be
// after just writing to the "global" scope
result.push(window.$);
result.push($);
""")
)
# The compiled source of that scripts with some additional setup
# bookending it.
cls.test_script = "\n".join([
"var result = [];",
test_script.code(),
"""
// Now check that the actual global scope has
// not been overwritten
result.push(window.$);
result.push($);
// And return our findings
result;"""
])
# What we expect the script to report back.
cls.expected = [
"global", "global",
"shadowed", "shadowed",
"global", "global"]
def test_webengine(self, callback_checker, webengineview):
page = webengineview.page()
page.runJavaScript(self.setup_script)
page.runJavaScript(self.test_script, callback_checker.callback)
callback_checker.check(self.expected)
def test_webkit(self, webview):
elem = webview.page().mainFrame().documentElement()
elem.evaluateJavaScript(self.setup_script)
result = elem.evaluateJavaScript(self.test_script)
assert result == self.expected