1from tests.support.asserts import assert_error, assert_success
2import pytest
3
4def query(session, name):
5    script = """
6        var done = arguments[0];
7        navigator.permissions.query({ name: '%s' })
8          .then(function(value) {
9              done({ status: 'success', value: value && value.state });
10            }, function(error) {
11              done({ status: 'error', value: error && error.message });
12            });
13    """ % name
14
15    return session.transport.send(
16        "POST", "/session/{session_id}/execute/async".format(**vars(session)),
17        {"script": script, "args": []})
18
19# > 1. Let parameters be the parameters argument, converted to an IDL value of
20# >    type PermissionSetParameters. If this throws an exception, return a
21# >    WebDriver error with WebDriver error code invalid argument.
22@pytest.mark.parametrize("parameters", [
23    #{ "descriptor": { "name": "geolocation" }, "state": "granted" }
24    { "descriptor": { "name": 23 }, "state": "granted" },
25    { "descriptor": { }, "state": "granted" },
26    { "descriptor": { "name": "geolocation" }, "state": "Granted" },
27    { "descriptor": 23, "state": "granted" },
28    { "descriptor": "geolocation", "state": "granted" },
29    { "descriptor": [ { "name": "geolocation" } ], "state": "granted" },
30    [ { "descriptor": { "name": "geolocation" }, "state": "granted" } ],
31    { "descriptor": { "name": "geolocation" }, "state": "granted", "oneRealm": 23 }
32])
33@pytest.mark.capabilities({"acceptInsecureCerts": True})
34def test_invalid_parameters(session, url, parameters):
35    session.url = url("/common/blank.html", protocol="https")
36    response = session.transport.send(
37        "POST",
38        "/session/{session_id}/permissions".format(**vars(session)),
39        parameters
40    )
41    assert_error(response, "invalid argument")
42
43# > 6. If settings is a non-secure context and rootDesc.name isn't allowed in
44# >    non-secure contexts, return a WebDriver error with WebDriver error code
45# >    invalid argument.
46@pytest.mark.parametrize("state", ["granted", "denied", "prompt"])
47def test_non_secure_context(session, url, state):
48    session.url = url("/common/blank.html", protocol="http")
49    response = session.transport.send(
50        "POST", "/session/{session_id}/permissions".format(**vars(session)),
51        { "descriptor": { "name": "push" }, "state": state }
52    )
53
54    assert_error(response, "invalid argument")
55
56@pytest.mark.parametrize("state", ["granted", "denied", "prompt"])
57@pytest.mark.parametrize("realmSetting", [
58    { "oneRealm": True },
59    { "oneRealm": False },
60    {}
61])
62@pytest.mark.capabilities({"acceptInsecureCerts": True})
63def test_set_to_state(session, url, state, realmSetting):
64    session.url = url("/common/blank.html", protocol="https")
65    parameters = { "descriptor": { "name": "geolocation" }, "state": state }
66    parameters.update(realmSetting)
67    response = session.transport.send(
68        "POST", "/session/{session_id}/permissions".format(**vars(session)),
69        parameters
70    )
71
72    try:
73        assert_success(response)
74    except AssertionError:
75        # > 4. If parameters.state is an inappropriate permission state for any
76        # >    implementation-defined reason, return a WebDriver error with
77        # >    WebDriver error code invalid argument.
78        assert_error(response, "invalid argument")
79        return
80
81    assert response.body.get("value") == None
82
83    response = query(session, "geolocation")
84
85    assert_success(response)
86    result = response.body.get("value")
87
88    assert isinstance(result, dict)
89    assert result.get("status") == "success"
90    assert result.get("value") == state
91
92# > 7. If parameters.oneRealm is true, [...]
93# > 8. Otherwise, let targets be a list containing all environment settings
94# >    objects whose origin is the same as the origin of settings.
95#
96# Ensure that all realms are affected when `oneRealm` is not enabled.
97@pytest.mark.parametrize("state", ["granted", "denied", "prompt"])
98@pytest.mark.parametrize("realmSetting", [
99    { "oneRealm": False },
100    {}
101])
102@pytest.mark.capabilities({"acceptInsecureCerts": True})
103def test_set_to_state_cross_realm(session, url, state, realmSetting):
104    session.url = url("/common/blank.html", protocol="https")
105    original_window = session.window_handle
106    session.window_handle = session.new_window()
107    session.url = url("/common/blank.html", protocol="https")
108    parameters = { "descriptor": { "name": "geolocation" }, "state": state }
109    parameters.update(realmSetting)
110
111    response = session.transport.send(
112        "POST", "/session/{session_id}/permissions".format(**vars(session)),
113        parameters
114    )
115
116    try:
117        assert_success(response)
118    except AssertionError:
119        # > 4. If parameters.state is an inappropriate permission state for any
120        # >    implementation-defined reason, return a WebDriver error with
121        # >    WebDriver error code invalid argument.
122        assert_error(response, "invalid argument")
123        return
124
125    assert response.body.get("value") == None
126
127    session.window_handle = original_window
128
129    response = query(session, "geolocation")
130
131    assert_success(response)
132    result = response.body.get("value")
133
134    assert isinstance(result, dict)
135    assert result.get("status") == "success"
136    assert result.get("value") == state
137
138# The following test is not implemented because UAs may vary in the way they
139# modify permissions across realms, so the behavior of the `oneRealm` parameter
140# cannot be asserted uniformly.
141# def test_set_to_state_one_realm():
142#     pass
143