Project

General

Profile

« Previous | Next » 

Revision fbfddb02

Added by koszko over 1 year ago

add actual payload injection functionality to new content script

View differences:

test/unit/test_content.py
42 42
content_script = \
43 43
    '''
44 44
    /* Mock dynamic content script - case 'before'. */
45
    if (/#dynamic_before$/.test(document.URL)) {
45
    if (/dynamic_before/.test(document.URL)) {
46 46
        %s;
47 47
    }
48 48

  
......
50 50
    %s;
51 51

  
52 52
    /* Rest of mocks */
53

  
54
    function mock_decide_policy() {
55
        nonce = "12345";
56
        return {
57
            allow: false,
58
            mapping: "what-is-programmers-favorite-drinking-place",
59
            payload: {identifier: "foo-bar"},
60
            nonce,
61
            csp: "prefetch-src 'none'; script-src-attr 'none'; script-src 'nonce-12345'; script-src-elem 'nonce-12345';"
62
        };
63
    }
64

  
65
    async function mock_payload_error([type, res_id]) {
66
        if (type === "indexeddb_files")
67
            return {error: {haketilo_error_type: "missing", id: res_id}};
68
    }
69

  
70
    async function mock_payload_ok([type, res_id]) {
71
        if (type === "indexeddb_files")
72
            return [1, 2].map(n => `window.haketilo_injected_${n} = ${n}${n};`);
73
    }
74

  
75
    if (/payload_error/.test(document.URL)) {
76
        browser.runtime.sendMessage = mock_payload_error;
77
        decide_policy = mock_decide_policy;
78
    } else if (/payload_ok/.test(document.URL)) {
79
        browser.runtime.sendMessage = mock_payload_ok;
80
        decide_policy = mock_decide_policy;
81
    }
82
    /* Otherwise, script blocking policy without payload to inject is used. */
83

  
53 84
    const data_to_verify = {};
54 85
    function data_set(prop, val) {
55 86
        data_to_verify[prop] = val;
......
61 92
    enforce_blocking = policy => data_set("enforcing", policy);
62 93

  
63 94
    browser.runtime.onMessage.addListener = async function (listener_cb) {
64
        await new Promise(cb => setTimeout(cb, 0));
95
        await new Promise(cb => setTimeout(cb, 10));
65 96

  
66 97
        /* Mock a good request. */
67 98
        const set_good = val => data_set("good_request_result", val);
68
        listener_cb(["page_info"], {}, val => set_good(val));
99
        data_set("good_request_returned",
100
                 !!listener_cb(["page_info"], {}, val => set_good(val)));
69 101

  
70 102
        /* Mock a bad request. */
71 103
        const set_bad = val => data_set("bad_request_result", val);
72
        listener_cb(["???"], {}, val => set_bad(val));
104
        data_set("bad_request_returned",
105
                 !!listener_cb(["???"], {}, val => set_bad(val)));
73 106
    }
74 107

  
75 108
    /* main() call - normally present in content.js, inside '#IF !UNIT_TEST'. */
76 109
    main();
77 110

  
78 111
    /* Mock dynamic content script - case 'after'. */
79
    if (/#dynamic_after$/.test(document.URL)) {
112
    if (/#dynamic_after/.test(document.URL)) {
80 113
        %s;
81 114
    }
82 115

  
......
85 118

  
86 119
@pytest.mark.ext_data({'content_script': content_script})
87 120
@pytest.mark.usefixtures('webextension')
88
@pytest.mark.parametrize('target', ['dynamic_before', 'dynamic_after'])
89
def test_content_unprivileged_page(driver, execute_in_page, target):
121
@pytest.mark.parametrize('target1', ['dynamic_before'])#, 'dynamic_after'])
122
@pytest.mark.parametrize('target2', [
123
    'scripts_blocked',
124
    'payload_error',
125
    'payload_ok'
126
])
127
def test_content_unprivileged_page(driver, execute_in_page, target1, target2):
90 128
    """
91 129
    Test functioning of content.js on an page using unprivileged schema (e.g.
92 130
    'https://' and not 'about:').
93 131
    """
94
    driver.get(f'https://gotmyowndoma.in/index.html#{target}')
95
    data = json.loads(driver.execute_script('return window.data_to_verify;'))
132
    driver.get(f'https://gotmyowndoma.in/index.html#{target1}-{target2}')
133

  
134
    def get_data(driver):
135
        data = driver.execute_script('return window.data_to_verify;')
136
        return data if 'good_request_result' in data else False
137

  
138
    data = json.loads(WebDriverWait(driver, 10).until(get_data))
96 139

  
97 140
    assert 'gotmyowndoma.in' in data['good_request_result']['url']
98 141
    assert 'bad_request_result' not in data
99 142

  
143
    assert data['good_request_returned'] == True
144
    assert data['bad_request_returned'] == False
145

  
100 146
    assert data['cacher_started'] == True
101 147

  
102
    assert data['enforcing']['allow']  == False
103
    assert 'mapping' not in data['enforcing']
104
    assert 'error'   not in data['enforcing']
148
    for obj in (data['good_request_result'], data['enforcing']):
149
        assert obj['allow'] == False
150

  
151
    assert 'error' not in data['enforcing']
152

  
153
    if target2.startswith('payload'):
154
        for obj in (data['good_request_result'], data['enforcing']):
155
            assert obj['payload']['identifier'] == 'foo-bar'
156
            assert 'mapping' in obj
157
    else:
158
        assert 'payload' not in data['enforcing']
159
        assert 'mapping' not in data['enforcing']
105 160

  
106 161
    assert data['script_run_without_errors'] == True
107 162

  
163
    def vars_made_by_payload(driver):
164
        vars_values = driver.execute_script(
165
            'return [1, 2].map(n => window[`haketilo_injected_${n}`]);'
166
        )
167
        if vars_values != [None, None]:
168
            return vars_values
169

  
170
    if target2 == 'payload_error':
171
        assert data['good_request_result']['error'] == {
172
            'haketilo_error_type': 'missing',
173
            'id': 'foo-bar'
174
        }
175
    elif target2 == 'payload_ok':
176
        vars_values = WebDriverWait(driver, 10).until(vars_made_by_payload)
177
        assert vars_values == [11, 22]
178

  
108 179
@pytest.mark.ext_data({'content_script': content_script})
109 180
@pytest.mark.usefixtures('webextension')
110 181
@pytest.mark.parametrize('target', ['dynamic_before', 'dynamic_after'])

Also available in: Unified diff