mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1769791, part 1 - Remove support for setting permissions in mozprofile. r=jmaher
The only permission that is set is allowXULXBL, and we don't want to set that by default, because we don't normally allow XUL in web content. It can be enabled on an individual test by adding allow_xul_xbl = true to a test manifest, or by using pushPermissions within the test. This also removes the noxul test server, because no XUL is now the default behavior. Differential Revision: https://phabricator.services.mozilla.com/D148136
This commit is contained in:
parent
d9c49a3262
commit
a3fb85df7b
@ -94,7 +94,6 @@ http://sub1.test1.example.com:80 privileged
|
|||||||
http://sub1.test2.example.com:80 privileged
|
http://sub1.test2.example.com:80 privileged
|
||||||
http://sub2.test1.example.com:80 privileged
|
http://sub2.test1.example.com:80 privileged
|
||||||
http://sub2.test2.example.com:80 privileged
|
http://sub2.test2.example.com:80 privileged
|
||||||
http://noxul.example.com:80 privileged,noxul
|
|
||||||
http://example.net:80 privileged
|
http://example.net:80 privileged
|
||||||
http://supports-insecure.expired.example.com:80 privileged
|
http://supports-insecure.expired.example.com:80 privileged
|
||||||
# Used to test that clearing Service Workers for domain example.com, does not clear prefixexample.com
|
# Used to test that clearing Service Workers for domain example.com, does not clear prefixexample.com
|
||||||
|
@ -11,11 +11,9 @@ from __future__ import absolute_import
|
|||||||
|
|
||||||
import codecs
|
import codecs
|
||||||
import os
|
import os
|
||||||
import sqlite3
|
|
||||||
|
|
||||||
from six import string_types
|
from six import string_types
|
||||||
from six.moves.urllib import parse
|
from six.moves.urllib import parse
|
||||||
import six
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"MissingPrimaryLocationError",
|
"MissingPrimaryLocationError",
|
||||||
@ -128,8 +126,7 @@ class ServerLocations(object):
|
|||||||
callback is called, if given.
|
callback is called, if given.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, filename=None, add_callback=None):
|
def __init__(self, filename=None):
|
||||||
self.add_callback = add_callback
|
|
||||||
self._locations = []
|
self._locations = []
|
||||||
self.hasPrimary = False
|
self.hasPrimary = False
|
||||||
if filename:
|
if filename:
|
||||||
@ -141,15 +138,13 @@ class ServerLocations(object):
|
|||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self._locations)
|
return len(self._locations)
|
||||||
|
|
||||||
def add(self, location, suppress_callback=False):
|
def add(self, location):
|
||||||
if "primary" in location.options:
|
if "primary" in location.options:
|
||||||
if self.hasPrimary:
|
if self.hasPrimary:
|
||||||
raise MultiplePrimaryLocationsError()
|
raise MultiplePrimaryLocationsError()
|
||||||
self.hasPrimary = True
|
self.hasPrimary = True
|
||||||
|
|
||||||
self._locations.append(location)
|
self._locations.append(location)
|
||||||
if self.add_callback and not suppress_callback:
|
|
||||||
self.add_callback([location])
|
|
||||||
|
|
||||||
def add_host(self, host, port="80", scheme="http", options="privileged"):
|
def add_host(self, host, port="80", scheme="http", options="privileged"):
|
||||||
if isinstance(options, string_types):
|
if isinstance(options, string_types):
|
||||||
@ -205,7 +200,7 @@ class ServerLocations(object):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
location = Location(scheme, host, port, options)
|
location = Location(scheme, host, port, options)
|
||||||
self.add(location, suppress_callback=True)
|
self.add(location)
|
||||||
except LocationError as e:
|
except LocationError as e:
|
||||||
raise LocationsSyntaxError(lineno, e)
|
raise LocationsSyntaxError(lineno, e)
|
||||||
|
|
||||||
@ -215,21 +210,15 @@ class ServerLocations(object):
|
|||||||
if check_for_primary and not self.hasPrimary:
|
if check_for_primary and not self.hasPrimary:
|
||||||
raise LocationsSyntaxError(lineno + 1, MissingPrimaryLocationError())
|
raise LocationsSyntaxError(lineno + 1, MissingPrimaryLocationError())
|
||||||
|
|
||||||
if self.add_callback:
|
|
||||||
self.add_callback(new_locations)
|
|
||||||
|
|
||||||
|
|
||||||
class Permissions(object):
|
class Permissions(object):
|
||||||
"""Allows handling of permissions for ``mozprofile``"""
|
"""Allows handling of permissions for ``mozprofile``"""
|
||||||
|
|
||||||
def __init__(self, profileDir, locations=None):
|
def __init__(self, locations=None):
|
||||||
self._profileDir = profileDir
|
self._locations = ServerLocations()
|
||||||
self._locations = ServerLocations(add_callback=self.write_db)
|
|
||||||
if locations:
|
if locations:
|
||||||
if isinstance(locations, ServerLocations):
|
if isinstance(locations, ServerLocations):
|
||||||
self._locations = locations
|
self._locations = locations
|
||||||
self._locations.add_callback = self.write_db
|
|
||||||
self.write_db(self._locations._locations)
|
|
||||||
elif isinstance(locations, list):
|
elif isinstance(locations, list):
|
||||||
for l in locations:
|
for l in locations:
|
||||||
self._locations.add_host(**l)
|
self._locations.add_host(**l)
|
||||||
@ -238,82 +227,6 @@ class Permissions(object):
|
|||||||
elif os.path.exists(locations):
|
elif os.path.exists(locations):
|
||||||
self._locations.read(locations)
|
self._locations.read(locations)
|
||||||
|
|
||||||
def write_db(self, locations):
|
|
||||||
"""write permissions to the sqlite database"""
|
|
||||||
|
|
||||||
# Open database and create table
|
|
||||||
permDB = sqlite3.connect(os.path.join(self._profileDir, "permissions.sqlite"))
|
|
||||||
cursor = permDB.cursor()
|
|
||||||
|
|
||||||
# SQL copied from
|
|
||||||
# http://searchfox.org/mozilla-central/source/extensions/permissions/PermissionManager.cpp
|
|
||||||
cursor.execute(
|
|
||||||
"""CREATE TABLE IF NOT EXISTS moz_hosts (
|
|
||||||
id INTEGER PRIMARY KEY
|
|
||||||
,origin TEXT
|
|
||||||
,type TEXT
|
|
||||||
,permission INTEGER
|
|
||||||
,expireType INTEGER
|
|
||||||
,expireTime INTEGER
|
|
||||||
,modificationTime INTEGER
|
|
||||||
)"""
|
|
||||||
)
|
|
||||||
|
|
||||||
rows = cursor.execute("PRAGMA table_info(moz_hosts)")
|
|
||||||
count = len(rows.fetchall())
|
|
||||||
|
|
||||||
using_origin = False
|
|
||||||
# if the db contains 7 columns, we're using user_version 5
|
|
||||||
if count == 7:
|
|
||||||
statement = "INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0, 0)"
|
|
||||||
cursor.execute("PRAGMA user_version=5;")
|
|
||||||
using_origin = True
|
|
||||||
# if the db contains 9 columns, we're using user_version 4
|
|
||||||
elif count == 9:
|
|
||||||
statement = "INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0, 0, 0, 0)"
|
|
||||||
cursor.execute("PRAGMA user_version=4;")
|
|
||||||
# if the db contains 8 columns, we're using user_version 3
|
|
||||||
elif count == 8:
|
|
||||||
statement = "INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0, 0, 0)"
|
|
||||||
cursor.execute("PRAGMA user_version=3;")
|
|
||||||
else:
|
|
||||||
statement = "INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0)"
|
|
||||||
cursor.execute("PRAGMA user_version=2;")
|
|
||||||
|
|
||||||
for location in locations:
|
|
||||||
# set the permissions
|
|
||||||
permissions = {"allowXULXBL": "noxul" not in location.options}
|
|
||||||
for perm, allow in six.iteritems(permissions):
|
|
||||||
if allow:
|
|
||||||
permission_type = 1
|
|
||||||
else:
|
|
||||||
permission_type = 2
|
|
||||||
|
|
||||||
if using_origin:
|
|
||||||
# This is a crude approximation of the origin generation
|
|
||||||
# logic from ContentPrincipal and nsStandardURL. It should
|
|
||||||
# suffice for the permissions which the test runners will
|
|
||||||
# want to insert into the system.
|
|
||||||
origin = location.scheme + "://" + location.host
|
|
||||||
if (location.scheme != "http" or location.port != "80") and (
|
|
||||||
location.scheme != "https" or location.port != "443"
|
|
||||||
):
|
|
||||||
origin += ":" + str(location.port)
|
|
||||||
|
|
||||||
cursor.execute(statement, (origin, perm, permission_type))
|
|
||||||
else:
|
|
||||||
# The database is still using a legacy system based on hosts
|
|
||||||
# We can insert the permission as a host
|
|
||||||
#
|
|
||||||
# XXX This codepath should not be hit, as tests are run with
|
|
||||||
# fresh profiles. However, if it was hit, permissions would
|
|
||||||
# not be added to the database correctly (bug 1183185).
|
|
||||||
cursor.execute(statement, (location.host, perm, permission_type))
|
|
||||||
|
|
||||||
# Commit and close
|
|
||||||
permDB.commit()
|
|
||||||
cursor.close()
|
|
||||||
|
|
||||||
def network_prefs(self, proxy=None):
|
def network_prefs(self, proxy=None):
|
||||||
"""
|
"""
|
||||||
take known locations and generate preferences to handle permissions and proxy
|
take known locations and generate preferences to handle permissions and proxy
|
||||||
@ -411,22 +324,3 @@ function FindProxyForURL(url, host)
|
|||||||
prefs.append(("network.proxy.autoconfig_url", pacURL))
|
prefs.append(("network.proxy.autoconfig_url", pacURL))
|
||||||
|
|
||||||
return prefs
|
return prefs
|
||||||
|
|
||||||
def clean_db(self):
|
|
||||||
"""Removed permissions added by mozprofile."""
|
|
||||||
|
|
||||||
sqlite_file = os.path.join(self._profileDir, "permissions.sqlite")
|
|
||||||
if not os.path.exists(sqlite_file):
|
|
||||||
return
|
|
||||||
|
|
||||||
# Open database and create table
|
|
||||||
permDB = sqlite3.connect(sqlite_file)
|
|
||||||
cursor = permDB.cursor()
|
|
||||||
|
|
||||||
# TODO: only delete values that we add, this would require sending
|
|
||||||
# in the full permissions object
|
|
||||||
cursor.execute("DROP TABLE IF EXISTS moz_hosts")
|
|
||||||
|
|
||||||
# Commit and close
|
|
||||||
permDB.commit()
|
|
||||||
cursor.close()
|
|
||||||
|
@ -248,7 +248,7 @@ class Profile(BaseProfile):
|
|||||||
# Set additional preferences
|
# Set additional preferences
|
||||||
self.set_preferences(self._preferences)
|
self.set_preferences(self._preferences)
|
||||||
|
|
||||||
self.permissions = Permissions(self.profile, self._locations)
|
self.permissions = Permissions(self._locations)
|
||||||
prefs_js, user_js = self.permissions.network_prefs(self._proxy)
|
prefs_js, user_js = self.permissions.network_prefs(self._proxy)
|
||||||
|
|
||||||
if self._whitelistpaths:
|
if self._whitelistpaths:
|
||||||
@ -293,8 +293,6 @@ class Profile(BaseProfile):
|
|||||||
self.clean_preferences()
|
self.clean_preferences()
|
||||||
if getattr(self, "addons", None) is not None:
|
if getattr(self, "addons", None) is not None:
|
||||||
self.addons.clean()
|
self.addons.clean()
|
||||||
if getattr(self, "permissions", None) is not None:
|
|
||||||
self.permissions.clean_db()
|
|
||||||
super(Profile, self).cleanup()
|
super(Profile, self).cleanup()
|
||||||
|
|
||||||
def clean_preferences(self):
|
def clean_preferences(self):
|
||||||
|
@ -6,16 +6,12 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import os
|
|
||||||
import sqlite3
|
|
||||||
|
|
||||||
import mozunit
|
import mozunit
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mozprofile.permissions import Permissions
|
from mozprofile.permissions import Permissions
|
||||||
|
|
||||||
LOCATIONS = """http://mochi.test:8888 primary,privileged
|
LOCATIONS = """http://mochi.test:8888 primary,privileged
|
||||||
http://127.0.0.1:80 noxul
|
|
||||||
http://127.0.0.1:8888 privileged
|
http://127.0.0.1:8888 privileged
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -29,54 +25,7 @@ def locations_file(tmpdir):
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def perms(tmpdir, locations_file):
|
def perms(tmpdir, locations_file):
|
||||||
return Permissions(tmpdir.mkdir("profile").strpath, locations_file)
|
return Permissions(locations_file)
|
||||||
|
|
||||||
|
|
||||||
def test_create_permissions_db(perms):
|
|
||||||
profile_dir = perms._profileDir
|
|
||||||
perms_db_filename = os.path.join(profile_dir, "permissions.sqlite")
|
|
||||||
|
|
||||||
select_stmt = "select origin, type, permission from moz_hosts"
|
|
||||||
|
|
||||||
con = sqlite3.connect(perms_db_filename)
|
|
||||||
cur = con.cursor()
|
|
||||||
cur.execute(select_stmt)
|
|
||||||
entries = cur.fetchall()
|
|
||||||
|
|
||||||
assert len(entries) == 3
|
|
||||||
|
|
||||||
assert entries[0][0] == "http://mochi.test:8888"
|
|
||||||
assert entries[0][1] == "allowXULXBL"
|
|
||||||
assert entries[0][2] == 1
|
|
||||||
|
|
||||||
assert entries[1][0] == "http://127.0.0.1"
|
|
||||||
assert entries[1][1] == "allowXULXBL"
|
|
||||||
assert entries[1][2] == 2
|
|
||||||
|
|
||||||
assert entries[2][0] == "http://127.0.0.1:8888"
|
|
||||||
assert entries[2][1] == "allowXULXBL"
|
|
||||||
assert entries[2][2] == 1
|
|
||||||
|
|
||||||
perms._locations.add_host("a.b.c", port="8081", scheme="https", options="noxul")
|
|
||||||
|
|
||||||
cur.execute(select_stmt)
|
|
||||||
entries = cur.fetchall()
|
|
||||||
|
|
||||||
assert len(entries) == 4
|
|
||||||
assert entries[3][0] == "https://a.b.c:8081"
|
|
||||||
assert entries[3][1] == "allowXULXBL"
|
|
||||||
assert entries[3][2] == 2
|
|
||||||
|
|
||||||
# when creating a DB we should default to user_version==5
|
|
||||||
cur.execute("PRAGMA user_version")
|
|
||||||
entries = cur.fetchall()
|
|
||||||
assert entries[0][0] == 5
|
|
||||||
|
|
||||||
perms.clean_db()
|
|
||||||
# table should be removed
|
|
||||||
cur.execute("select * from sqlite_master where type='table'")
|
|
||||||
entries = cur.fetchall()
|
|
||||||
assert len(entries) == 0
|
|
||||||
|
|
||||||
|
|
||||||
def test_nw_prefs(perms):
|
def test_nw_prefs(perms):
|
||||||
@ -92,7 +41,7 @@ def test_nw_prefs(perms):
|
|||||||
|
|
||||||
origins_decl = (
|
origins_decl = (
|
||||||
"var knownOrigins = (function () { return ['http://mochi.test:8888', "
|
"var knownOrigins = (function () { return ['http://mochi.test:8888', "
|
||||||
"'http://127.0.0.1:80', 'http://127.0.0.1:8888'].reduce"
|
"'http://127.0.0.1:8888'].reduce"
|
||||||
)
|
)
|
||||||
assert origins_decl in user_prefs[1][1]
|
assert origins_decl in user_prefs[1][1]
|
||||||
|
|
||||||
@ -105,121 +54,5 @@ def test_nw_prefs(perms):
|
|||||||
assert all(c in user_prefs[1][1] for c in proxy_check)
|
assert all(c in user_prefs[1][1] for c in proxy_check)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def perms_db_filename(tmpdir):
|
|
||||||
return tmpdir.join("permissions.sqlite").strpath
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def permDB(perms_db_filename):
|
|
||||||
permDB = sqlite3.connect(perms_db_filename)
|
|
||||||
yield permDB
|
|
||||||
permDB.cursor().close()
|
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=W1638
|
|
||||||
@pytest.fixture(params=range(2, 6))
|
|
||||||
def version(request, perms_db_filename, permDB, locations_file):
|
|
||||||
version = request.param
|
|
||||||
|
|
||||||
cursor = permDB.cursor()
|
|
||||||
cursor.execute("PRAGMA user_version=%d;" % version)
|
|
||||||
|
|
||||||
if version == 5:
|
|
||||||
cursor.execute(
|
|
||||||
"""CREATE TABLE IF NOT EXISTS moz_hosts (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
origin TEXT,
|
|
||||||
type TEXT,
|
|
||||||
permission INTEGER,
|
|
||||||
expireType INTEGER,
|
|
||||||
expireTime INTEGER,
|
|
||||||
modificationTime INTEGER)"""
|
|
||||||
)
|
|
||||||
elif version == 4:
|
|
||||||
cursor.execute(
|
|
||||||
"""CREATE TABLE IF NOT EXISTS moz_hosts (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
host TEXT,
|
|
||||||
type TEXT,
|
|
||||||
permission INTEGER,
|
|
||||||
expireType INTEGER,
|
|
||||||
expireTime INTEGER,
|
|
||||||
modificationTime INTEGER,
|
|
||||||
appId INTEGER,
|
|
||||||
isInBrowserElement INTEGER)"""
|
|
||||||
)
|
|
||||||
elif version == 3:
|
|
||||||
cursor.execute(
|
|
||||||
"""CREATE TABLE IF NOT EXISTS moz_hosts (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
host TEXT,
|
|
||||||
type TEXT,
|
|
||||||
permission INTEGER,
|
|
||||||
expireType INTEGER,
|
|
||||||
expireTime INTEGER,
|
|
||||||
appId INTEGER,
|
|
||||||
isInBrowserElement INTEGER)"""
|
|
||||||
)
|
|
||||||
elif version == 2:
|
|
||||||
cursor.execute(
|
|
||||||
"""CREATE TABLE IF NOT EXISTS moz_hosts (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
host TEXT,
|
|
||||||
type TEXT,
|
|
||||||
permission INTEGER,
|
|
||||||
expireType INTEGER,
|
|
||||||
expireTime INTEGER)"""
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
raise Exception("version must be 2, 3, 4 or 5")
|
|
||||||
permDB.commit()
|
|
||||||
|
|
||||||
# Create a permissions object to read the db
|
|
||||||
Permissions(os.path.dirname(perms_db_filename), locations_file)
|
|
||||||
return version
|
|
||||||
|
|
||||||
|
|
||||||
def test_verify_user_version(version, permDB):
|
|
||||||
"""Verifies that we call INSERT statements using the correct number
|
|
||||||
of columns for existing databases.
|
|
||||||
"""
|
|
||||||
select_stmt = "select * from moz_hosts"
|
|
||||||
|
|
||||||
cur = permDB.cursor()
|
|
||||||
cur.execute(select_stmt)
|
|
||||||
entries = cur.fetchall()
|
|
||||||
|
|
||||||
assert len(entries) == 3
|
|
||||||
|
|
||||||
columns = {
|
|
||||||
1: 6,
|
|
||||||
2: 6,
|
|
||||||
3: 8,
|
|
||||||
4: 9,
|
|
||||||
5: 7,
|
|
||||||
}[version]
|
|
||||||
|
|
||||||
assert len(entries[0]) == columns
|
|
||||||
for x in range(4, columns):
|
|
||||||
assert entries[0][x] == 0
|
|
||||||
|
|
||||||
|
|
||||||
def test_schema_version(perms, locations_file):
|
|
||||||
profile_dir = perms._profileDir
|
|
||||||
perms_db_filename = os.path.join(profile_dir, "permissions.sqlite")
|
|
||||||
perms.write_db(open(locations_file, "w+b"))
|
|
||||||
|
|
||||||
stmt = "PRAGMA user_version;"
|
|
||||||
|
|
||||||
con = sqlite3.connect(perms_db_filename)
|
|
||||||
cur = con.cursor()
|
|
||||||
cur.execute(stmt)
|
|
||||||
entries = cur.fetchall()
|
|
||||||
|
|
||||||
schema_version = entries[0][0]
|
|
||||||
assert schema_version == 5
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
mozunit.main()
|
mozunit.main()
|
||||||
|
@ -117,35 +117,5 @@ def test_server_locations(create_temp_file):
|
|||||||
assert exc.lineno == 4
|
assert exc.lineno == 4
|
||||||
|
|
||||||
|
|
||||||
def test_server_locations_callback(create_temp_file):
|
|
||||||
class CallbackTest(object):
|
|
||||||
last_locations = None
|
|
||||||
|
|
||||||
def callback(self, locations):
|
|
||||||
self.last_locations = locations
|
|
||||||
|
|
||||||
c = CallbackTest()
|
|
||||||
f = create_temp_file(LOCATIONS)
|
|
||||||
locations = ServerLocations(f, c.callback)
|
|
||||||
|
|
||||||
# callback should be for all locations in file
|
|
||||||
assert len(c.last_locations) == 6
|
|
||||||
|
|
||||||
# validate arbitrary one
|
|
||||||
compare_location(c.last_locations[2], "http", "127.0.0.1", "8888", ["privileged"])
|
|
||||||
|
|
||||||
locations.add_host("a.b.c")
|
|
||||||
|
|
||||||
# callback should be just for one location
|
|
||||||
assert len(c.last_locations) == 1
|
|
||||||
compare_location(c.last_locations[0], "http", "a.b.c", "80", ["privileged"])
|
|
||||||
|
|
||||||
# read a second file, which should generate a callback with both
|
|
||||||
# locations.
|
|
||||||
f = create_temp_file(LOCATIONS_NO_PRIMARY)
|
|
||||||
locations.read(f)
|
|
||||||
assert len(c.last_locations) == 2
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
mozunit.main()
|
mozunit.main()
|
||||||
|
Loading…
Reference in New Issue
Block a user