tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_preferences.py (13233B)


      1 #!/usr/bin/env python
      2 
      3 # This Source Code Form is subject to the terms of the Mozilla Public
      4 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 # You can obtain one at http://mozilla.org/MPL/2.0/.
      6 
      7 import os
      8 import shutil
      9 import tempfile
     10 
     11 import mozfile
     12 import mozunit
     13 import pytest
     14 from mozprofile.cli import MozProfileCLI
     15 from mozprofile.prefs import Preferences, PreferencesReadError
     16 from mozprofile.profile import Profile
     17 from wptserve import server
     18 
     19 here = os.path.dirname(os.path.abspath(__file__))
     20 
     21 
     22 # preferences from files/prefs_with_comments.js
     23 _prefs_with_comments = {
     24    "browser.startup.homepage": "http://planet.mozilla.org",
     25    "zoom.minPercent": 30,
     26    "zoom.maxPercent": 300,
     27    "webgl.verbose": "false",
     28 }
     29 
     30 
     31 @pytest.fixture
     32 def run_command():
     33    """
     34    invokes mozprofile command line via the CLI factory
     35    - args : command line arguments (equivalent of sys.argv[1:])
     36    """
     37 
     38    def inner(*args):
     39        # instantiate the factory
     40        cli = MozProfileCLI(list(args))
     41 
     42        # create the profile
     43        profile = cli.profile()
     44 
     45        # return path to profile
     46        return profile.profile
     47 
     48    return inner
     49 
     50 
     51 @pytest.fixture
     52 def compare_generated(run_command):
     53    """
     54    writes out to a new profile with mozprofile command line
     55    reads the generated preferences with prefs.py
     56    compares the results
     57    cleans up
     58    """
     59 
     60    def inner(prefs, commandline):
     61        profile = run_command(*commandline)
     62        prefs_file = os.path.join(profile, "user.js")
     63        assert os.path.exists(prefs_file)
     64        read = Preferences.read_prefs(prefs_file)
     65        if isinstance(prefs, dict):
     66            read = dict(read)
     67        assert prefs == read
     68        shutil.rmtree(profile)
     69 
     70    return inner
     71 
     72 
     73 def test_basic_prefs(compare_generated):
     74    """test setting a pref from the command line entry point"""
     75 
     76    _prefs = {"browser.startup.homepage": "http://planet.mozilla.org/"}
     77    commandline = []
     78    for pref, value in _prefs.items():
     79        commandline += ["--pref", "%s:%s" % (pref, value)]
     80    compare_generated(_prefs, commandline)
     81 
     82 
     83 def test_ordered_prefs(compare_generated):
     84    """ensure the prefs stay in the right order"""
     85    _prefs = [
     86        ("browser.startup.homepage", "http://planet.mozilla.org/"),
     87        ("zoom.minPercent", 30),
     88        ("zoom.maxPercent", 300),
     89        ("webgl.verbose", "false"),
     90    ]
     91    commandline = []
     92    for pref, value in _prefs:
     93        commandline += ["--pref", "%s:%s" % (pref, value)]
     94    _prefs = [(i, Preferences.cast(j)) for i, j in _prefs]
     95    compare_generated(_prefs, commandline)
     96 
     97 
     98 def test_ini(compare_generated):
     99    # write the .ini file
    100    _ini = """[DEFAULT]
    101 browser.startup.homepage = http://planet.mozilla.org/
    102 
    103 [foo]
    104 browser.startup.homepage = http://github.com/
    105 """
    106    try:
    107        fd, name = tempfile.mkstemp(suffix=".ini", text=True)
    108        os.write(fd, _ini.encode())
    109        os.close(fd)
    110        commandline = ["--preferences", name]
    111 
    112        # test the [DEFAULT] section
    113        _prefs = {"browser.startup.homepage": "http://planet.mozilla.org/"}
    114        compare_generated(_prefs, commandline)
    115 
    116        # test a specific section
    117        _prefs = {"browser.startup.homepage": "http://github.com/"}
    118        commandline[-1] = commandline[-1] + ":foo"
    119        compare_generated(_prefs, commandline)
    120 
    121    finally:
    122        # cleanup
    123        os.remove(name)
    124 
    125 
    126 def test_ini_keep_case(compare_generated):
    127    """
    128    Read a preferences config file with a preference in camel-case style.
    129    Check that the read preference name has not been lower-cased
    130    """
    131    # write the .ini file
    132    _ini = """[DEFAULT]
    133 network.dns.disableIPv6 = True
    134 """
    135    try:
    136        fd, name = tempfile.mkstemp(suffix=".ini", text=True)
    137        os.write(fd, _ini.encode())
    138        os.close(fd)
    139        commandline = ["--preferences", name]
    140 
    141        # test the [DEFAULT] section
    142        _prefs = {"network.dns.disableIPv6": "True"}
    143        compare_generated(_prefs, commandline)
    144 
    145    finally:
    146        # cleanup
    147        os.remove(name)
    148 
    149 
    150 def test_reset_should_remove_added_prefs():
    151    """Check that when we call reset the items we expect are updated"""
    152    profile = Profile()
    153    prefs_file = os.path.join(profile.profile, "user.js")
    154 
    155    # we shouldn't have any initial preferences
    156    initial_prefs = Preferences.read_prefs(prefs_file)
    157    assert not initial_prefs
    158    initial_prefs = open(prefs_file).read().strip()
    159    assert not initial_prefs
    160 
    161    # add some preferences
    162    prefs1 = [("mr.t.quotes", "i aint getting on no plane!")]
    163    profile.set_preferences(prefs1)
    164    assert prefs1 == Preferences.read_prefs(prefs_file)
    165    lines = open(prefs_file).read().strip().splitlines()
    166    assert any(line.startswith("#MozRunner Prefs Start") for line in lines)
    167    assert any(line.startswith("#MozRunner Prefs End") for line in lines)
    168 
    169    profile.reset()
    170    assert prefs1 != Preferences.read_prefs(os.path.join(profile.profile, "user.js"))
    171 
    172 
    173 def test_reset_should_keep_user_added_prefs():
    174    """Check that when we call reset the items we expect are updated"""
    175    profile = Profile()
    176    prefs_file = os.path.join(profile.profile, "user.js")
    177 
    178    # we shouldn't have any initial preferences
    179    initial_prefs = Preferences.read_prefs(prefs_file)
    180    assert not initial_prefs
    181    initial_prefs = open(prefs_file).read().strip()
    182    assert not initial_prefs
    183 
    184    # add some preferences
    185    prefs1 = [("mr.t.quotes", "i aint getting on no plane!")]
    186    profile.set_persistent_preferences(prefs1)
    187    assert prefs1 == Preferences.read_prefs(prefs_file)
    188    lines = open(prefs_file).read().strip().splitlines()
    189    assert any(line.startswith("#MozRunner Prefs Start") for line in lines)
    190    assert any(line.startswith("#MozRunner Prefs End") for line in lines)
    191 
    192    profile.reset()
    193    assert prefs1 == Preferences.read_prefs(os.path.join(profile.profile, "user.js"))
    194 
    195 
    196 def test_magic_markers():
    197    """ensure our magic markers are working"""
    198 
    199    profile = Profile()
    200    prefs_file = os.path.join(profile.profile, "user.js")
    201 
    202    # we shouldn't have any initial preferences
    203    initial_prefs = Preferences.read_prefs(prefs_file)
    204    assert not initial_prefs
    205    initial_prefs = open(prefs_file).read().strip()
    206    assert not initial_prefs
    207 
    208    # add some preferences
    209    prefs1 = [
    210        ("browser.startup.homepage", "http://planet.mozilla.org/"),
    211        ("zoom.minPercent", 30),
    212    ]
    213    profile.set_preferences(prefs1)
    214    assert prefs1 == Preferences.read_prefs(prefs_file)
    215    lines = open(prefs_file).read().strip().splitlines()
    216    assert bool([line for line in lines if line.startswith("#MozRunner Prefs Start")])
    217    assert bool([line for line in lines if line.startswith("#MozRunner Prefs End")])
    218 
    219    # add some more preferences
    220    prefs2 = [("zoom.maxPercent", 300), ("webgl.verbose", "false")]
    221    profile.set_preferences(prefs2)
    222    assert prefs1 + prefs2 == Preferences.read_prefs(prefs_file)
    223    lines = open(prefs_file).read().strip().splitlines()
    224    assert (
    225        len([line for line in lines if line.startswith("#MozRunner Prefs Start")]) == 2
    226    )
    227    assert len([line for line in lines if line.startswith("#MozRunner Prefs End")]) == 2
    228 
    229    # now clean it up
    230    profile.clean_preferences()
    231    final_prefs = Preferences.read_prefs(prefs_file)
    232    assert not final_prefs
    233    lines = open(prefs_file).read().strip().splitlines()
    234    assert "#MozRunner Prefs Start" not in lines
    235    assert "#MozRunner Prefs End" not in lines
    236 
    237 
    238 def test_preexisting_preferences():
    239    """ensure you don't clobber preexisting preferences"""
    240 
    241    # make a pretend profile
    242    tempdir = tempfile.mkdtemp()
    243 
    244    try:
    245        # make a user.js
    246        contents = """
    247 user_pref("webgl.enabled_for_all_sites", true);
    248 user_pref("webgl.force-enabled", true);
    249 """
    250        user_js = os.path.join(tempdir, "user.js")
    251        f = open(user_js, "w")
    252        f.write(contents)
    253        f.close()
    254 
    255        # make sure you can read it
    256        prefs = Preferences.read_prefs(user_js)
    257        original_prefs = [
    258            ("webgl.enabled_for_all_sites", True),
    259            ("webgl.force-enabled", True),
    260        ]
    261        assert prefs == original_prefs
    262 
    263        # now read this as a profile
    264        profile = Profile(
    265            tempdir, preferences={"browser.download.dir": "/home/jhammel"}
    266        )
    267 
    268        # make sure the new pref is now there
    269        new_prefs = original_prefs[:] + [("browser.download.dir", "/home/jhammel")]
    270        prefs = Preferences.read_prefs(user_js)
    271        assert prefs == new_prefs
    272 
    273        # clean up the added preferences
    274        profile.cleanup()
    275        del profile
    276 
    277        # make sure you have the original preferences
    278        prefs = Preferences.read_prefs(user_js)
    279        assert prefs == original_prefs
    280    finally:
    281        shutil.rmtree(tempdir)
    282 
    283 
    284 def test_can_read_prefs_with_multiline_comments():
    285    """
    286    Ensure that multiple comments in the file header do not break reading
    287    the prefs (https://bugzilla.mozilla.org/show_bug.cgi?id=1233534).
    288    """
    289    user_js = tempfile.NamedTemporaryFile(suffix=".js", delete=False)
    290    try:
    291        with user_js:
    292            user_js.write(
    293                b"""
    294 # Mozilla User Preferences
    295 
    296 /* Do not edit this file.
    297 *
    298 * If you make changes to this file while the application is running,
    299 * the changes will be overwritten when the application exits.
    300 *
    301 * To make a manual change to preferences, you can visit the URL about:config
    302 */
    303 
    304 user_pref("webgl.enabled_for_all_sites", true);
    305 user_pref("webgl.force-enabled", true);
    306 """
    307            )
    308        assert Preferences.read_prefs(user_js.name) == [
    309            ("webgl.enabled_for_all_sites", True),
    310            ("webgl.force-enabled", True),
    311        ]
    312    finally:
    313        mozfile.remove(user_js.name)
    314 
    315 
    316 def test_json(compare_generated):
    317    _prefs = {"browser.startup.homepage": "http://planet.mozilla.org/"}
    318    json = '{"browser.startup.homepage": "http://planet.mozilla.org/"}'
    319 
    320    # just repr it...could use the json module but we don't need it here
    321    with mozfile.NamedTemporaryFile(suffix=".json") as f:
    322        f.write(json.encode())
    323        f.flush()
    324 
    325        commandline = ["--preferences", f.name]
    326        compare_generated(_prefs, commandline)
    327 
    328 
    329 def test_json_datatypes():
    330    # minPercent is at 30.1 to test if non-integer data raises an exception
    331    json = """{"zoom.minPercent": 30.1, "zoom.maxPercent": 300}"""
    332 
    333    with mozfile.NamedTemporaryFile(suffix=".json") as f:
    334        f.write(json.encode())
    335        f.flush()
    336 
    337        with pytest.raises(PreferencesReadError):
    338            Preferences.read_json(f._path)
    339 
    340 
    341 def test_prefs_write():
    342    """test that the Preferences.write() method correctly serializes preferences"""
    343 
    344    _prefs = {
    345        "browser.startup.homepage": "http://planet.mozilla.org",
    346        "zoom.minPercent": 30,
    347        "zoom.maxPercent": 300,
    348    }
    349 
    350    # make a Preferences manager with the testing preferences
    351    preferences = Preferences(_prefs)
    352 
    353    # write them to a temporary location
    354    path = None
    355    read_prefs = None
    356    try:
    357        with mozfile.NamedTemporaryFile(suffix=".js", delete=False, mode="w+t") as f:
    358            path = f.name
    359            preferences.write(f, _prefs)
    360 
    361        # read them back and ensure we get what we put in
    362        read_prefs = dict(Preferences.read_prefs(path))
    363 
    364    finally:
    365        # cleanup
    366        if path and os.path.exists(path):
    367            os.remove(path)
    368 
    369    assert read_prefs == _prefs
    370 
    371 
    372 def test_read_prefs_with_comments():
    373    """test reading preferences from a prefs.js file that contains comments"""
    374 
    375    path = os.path.join(here, "files", "prefs_with_comments.js")
    376    assert dict(Preferences.read_prefs(path)) == _prefs_with_comments
    377 
    378 
    379 def test_read_prefs_with_interpolation():
    380    """test reading preferences from a prefs.js file whose values
    381    require interpolation"""
    382 
    383    expected_prefs = {
    384        "browser.foo": "http://server-name",
    385        "zoom.minPercent": 30,
    386        "webgl.verbose": "false",
    387        "browser.bar": "somethingxyz",
    388    }
    389    values = {"server": "server-name", "abc": "something"}
    390    path = os.path.join(here, "files", "prefs_with_interpolation.js")
    391    read_prefs = Preferences.read_prefs(path, interpolation=values)
    392    assert dict(read_prefs) == expected_prefs
    393 
    394 
    395 def test_read_prefs_with_multiline():
    396    """test reading preferences from a prefs.js file that contains multiline prefs"""
    397 
    398    path = os.path.join(here, "files", "prefs_with_multiline.js")
    399    assert dict(Preferences.read_prefs(path)) == {
    400        "browser.long.preference.name.that.causes.the.line.to.wrap": "itislong"
    401    }
    402 
    403 
    404 def test_read_prefs_ttw():
    405    """test reading preferences through the web via wptserve"""
    406 
    407    # create a WebTestHttpd instance
    408    docroot = os.path.join(here, "files")
    409    host = "127.0.0.1"
    410    port = 8888
    411    httpd = server.WebTestHttpd(host=host, port=port, doc_root=docroot)
    412 
    413    # create a preferences instance
    414    prefs = Preferences()
    415 
    416    try:
    417        # start server
    418        httpd.start()
    419 
    420        # read preferences through the web
    421        read = prefs.read_prefs("http://%s:%d/prefs_with_comments.js" % (host, port))
    422        assert dict(read) == _prefs_with_comments
    423    finally:
    424        httpd.stop()
    425 
    426 
    427 if __name__ == "__main__":
    428    mozunit.main()