mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 00:32:11 +00:00
Bug 1451733 - [mozprofile] Clean up the public facing addons API a bit r=jmaher
While we are removing a bunch of stuff and breaking backwards compatibility, I figured this would be a good time to also change some of the APIs. These APIs aren't used much in mozilla-central (and this patch updates the few places that do). This rolls the 'install_addons()' and 'install_addon_from_path' method into a single 'install' method. This install method can accept a string or list of paths to an individual addon (directory or .xpi), or a directory containing addons. This also renames Profile.addon_manager to Profile.addons, which reads better. MozReview-Commit-ID: 7vDPnG4cKqu --HG-- extra : rebase_source : 62f8613b9824e06e698d5af8dcbb4bcb07b8079e
This commit is contained in:
parent
caac402c4b
commit
69d04f8035
@ -120,11 +120,76 @@ class AddonManager(object):
|
||||
except AddonFormatError:
|
||||
return False
|
||||
|
||||
def install_addons(self, addons):
|
||||
"""
|
||||
Installs all types of addons
|
||||
def _install_addon(self, path, unpack=False):
|
||||
addons = [path]
|
||||
|
||||
:param addons: a list of addon paths to install
|
||||
# if path is not an add-on, try to install all contained add-ons
|
||||
try:
|
||||
self.addon_details(path)
|
||||
except AddonFormatError as e:
|
||||
module_logger.warning('Could not install %s: %s' % (path, str(e)))
|
||||
|
||||
# If the path doesn't exist, then we don't really care, just return
|
||||
if not os.path.isdir(path):
|
||||
return
|
||||
|
||||
addons = [os.path.join(path, x) for x in os.listdir(path) if
|
||||
self.is_addon(os.path.join(path, x))]
|
||||
addons.sort()
|
||||
|
||||
# install each addon
|
||||
for addon in addons:
|
||||
# determine the addon id
|
||||
addon_details = self.addon_details(addon)
|
||||
addon_id = addon_details.get('id')
|
||||
|
||||
# if the add-on has to be unpacked force it now
|
||||
# note: we might want to let Firefox do it in case of addon details
|
||||
orig_path = None
|
||||
if os.path.isfile(addon) and (unpack or addon_details['unpack']):
|
||||
orig_path = addon
|
||||
addon = tempfile.mkdtemp()
|
||||
mozfile.extract(orig_path, addon)
|
||||
|
||||
# copy the addon to the profile
|
||||
extensions_path = os.path.join(self.profile, 'extensions')
|
||||
addon_path = os.path.join(extensions_path, addon_id)
|
||||
|
||||
if os.path.isfile(addon):
|
||||
addon_path += '.xpi'
|
||||
|
||||
# move existing xpi file to backup location to restore later
|
||||
if os.path.exists(addon_path):
|
||||
self.backup_dir = self.backup_dir or tempfile.mkdtemp()
|
||||
shutil.move(addon_path, self.backup_dir)
|
||||
|
||||
# copy new add-on to the extension folder
|
||||
if not os.path.exists(extensions_path):
|
||||
os.makedirs(extensions_path)
|
||||
shutil.copy(addon, addon_path)
|
||||
else:
|
||||
# move existing folder to backup location to restore later
|
||||
if os.path.exists(addon_path):
|
||||
self.backup_dir = self.backup_dir or tempfile.mkdtemp()
|
||||
shutil.move(addon_path, self.backup_dir)
|
||||
|
||||
# copy new add-on to the extension folder
|
||||
shutil.copytree(addon, addon_path, symlinks=True)
|
||||
|
||||
# if we had to extract the addon, remove the temporary directory
|
||||
if orig_path:
|
||||
mozfile.remove(addon)
|
||||
addon = orig_path
|
||||
|
||||
self._addons.append(addon_id)
|
||||
self.installed_addons.append(addon)
|
||||
|
||||
def install(self, addons, **kwargs):
|
||||
"""
|
||||
Installs addons from a filepath or directory of addons in the profile.
|
||||
|
||||
:param addons: paths to .xpi or addon directories
|
||||
:param unpack: whether to unpack unless specified otherwise in the install.rdf
|
||||
"""
|
||||
if not addons:
|
||||
return
|
||||
@ -133,7 +198,7 @@ class AddonManager(object):
|
||||
if isinstance(addons, string_types):
|
||||
addons = [addons]
|
||||
for addon in set(addons):
|
||||
self.install_from_path(addon)
|
||||
self._install_addon(addon, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def _gen_iid(cls, addon_path):
|
||||
@ -256,76 +321,6 @@ class AddonManager(object):
|
||||
|
||||
return details
|
||||
|
||||
def install_from_path(self, path, unpack=False):
|
||||
"""
|
||||
Installs addon from a filepath or directory of addons in the profile.
|
||||
|
||||
:param path: path to .xpi or directory of addons
|
||||
:param unpack: whether to unpack unless specified otherwise in the install.rdf
|
||||
"""
|
||||
addons = [path]
|
||||
|
||||
# if path is not an add-on, try to install all contained add-ons
|
||||
try:
|
||||
self.addon_details(path)
|
||||
except AddonFormatError as e:
|
||||
module_logger.warning('Could not install %s: %s' % (path, str(e)))
|
||||
|
||||
# If the path doesn't exist, then we don't really care, just return
|
||||
if not os.path.isdir(path):
|
||||
return
|
||||
|
||||
addons = [os.path.join(path, x) for x in os.listdir(path) if
|
||||
self.is_addon(os.path.join(path, x))]
|
||||
addons.sort()
|
||||
|
||||
# install each addon
|
||||
for addon in addons:
|
||||
# determine the addon id
|
||||
addon_details = self.addon_details(addon)
|
||||
addon_id = addon_details.get('id')
|
||||
|
||||
# if the add-on has to be unpacked force it now
|
||||
# note: we might want to let Firefox do it in case of addon details
|
||||
orig_path = None
|
||||
if os.path.isfile(addon) and (unpack or addon_details['unpack']):
|
||||
orig_path = addon
|
||||
addon = tempfile.mkdtemp()
|
||||
mozfile.extract(orig_path, addon)
|
||||
|
||||
# copy the addon to the profile
|
||||
extensions_path = os.path.join(self.profile, 'extensions')
|
||||
addon_path = os.path.join(extensions_path, addon_id)
|
||||
|
||||
if os.path.isfile(addon):
|
||||
addon_path += '.xpi'
|
||||
|
||||
# move existing xpi file to backup location to restore later
|
||||
if os.path.exists(addon_path):
|
||||
self.backup_dir = self.backup_dir or tempfile.mkdtemp()
|
||||
shutil.move(addon_path, self.backup_dir)
|
||||
|
||||
# copy new add-on to the extension folder
|
||||
if not os.path.exists(extensions_path):
|
||||
os.makedirs(extensions_path)
|
||||
shutil.copy(addon, addon_path)
|
||||
else:
|
||||
# move existing folder to backup location to restore later
|
||||
if os.path.exists(addon_path):
|
||||
self.backup_dir = self.backup_dir or tempfile.mkdtemp()
|
||||
shutil.move(addon_path, self.backup_dir)
|
||||
|
||||
# copy new add-on to the extension folder
|
||||
shutil.copytree(addon, addon_path, symlinks=True)
|
||||
|
||||
# if we had to extract the addon, remove the temporary directory
|
||||
if orig_path:
|
||||
mozfile.remove(addon)
|
||||
addon = orig_path
|
||||
|
||||
self._addons.append(addon_id)
|
||||
self.installed_addons.append(addon)
|
||||
|
||||
def remove_addon(self, addon_id):
|
||||
"""Remove the add-on as specified by the id
|
||||
|
||||
|
@ -132,8 +132,8 @@ class Profile(object):
|
||||
self.set_preferences(user_js)
|
||||
|
||||
# handle add-on installation
|
||||
self.addon_manager = AddonManager(self.profile, restore=self.restore)
|
||||
self.addon_manager.install_addons(self._addons)
|
||||
self.addons = AddonManager(self.profile, restore=self.restore)
|
||||
self.addons.install(self._addons)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
@ -30,13 +30,13 @@ class TestAddonsManager(unittest.TestCase):
|
||||
self.logger.setLevel(mozlog.ERROR)
|
||||
|
||||
self.profile = mozprofile.profile.Profile()
|
||||
self.am = self.profile.addon_manager
|
||||
self.am = self.profile.addons
|
||||
|
||||
self.profile_path = self.profile.profile
|
||||
self.tmpdir = tempfile.mkdtemp()
|
||||
self.addCleanup(mozfile.remove, self.tmpdir)
|
||||
|
||||
def test_install_addons_multiple_same_source(self):
|
||||
def test_install_multiple_same_source(self):
|
||||
# Generate installer stubs for all possible types of addons
|
||||
addon_xpi = generate_addon('test-addon-1@mozilla.org',
|
||||
path=self.tmpdir)
|
||||
@ -45,18 +45,18 @@ class TestAddonsManager(unittest.TestCase):
|
||||
xpi=False)
|
||||
|
||||
# The same folder should not be installed twice
|
||||
self.am.install_addons([addon_folder, addon_folder])
|
||||
self.am.install([addon_folder, addon_folder])
|
||||
self.assertEqual(self.am.installed_addons, [addon_folder])
|
||||
self.am.clean()
|
||||
|
||||
# The same XPI file should not be installed twice
|
||||
self.am.install_addons([addon_xpi, addon_xpi])
|
||||
self.am.install([addon_xpi, addon_xpi])
|
||||
self.assertEqual(self.am.installed_addons, [addon_xpi])
|
||||
self.am.clean()
|
||||
|
||||
# Even if it is the same id the add-on should be installed twice, if
|
||||
# specified via XPI and folder
|
||||
self.am.install_addons([addon_folder, addon_xpi])
|
||||
self.am.install([addon_folder, addon_xpi])
|
||||
self.assertEqual(len(self.am.installed_addons), 2)
|
||||
self.assertIn(addon_folder, self.am.installed_addons)
|
||||
self.assertIn(addon_xpi, self.am.installed_addons)
|
||||
@ -69,13 +69,13 @@ class TestAddonsManager(unittest.TestCase):
|
||||
zipped.extractall(self.tmpdir)
|
||||
finally:
|
||||
zipped.close()
|
||||
self.am.install_from_path(self.tmpdir)
|
||||
self.am.install(self.tmpdir)
|
||||
self.assertEqual(len(self.am.installed_addons), 1)
|
||||
self.assertTrue(os.path.isdir(self.am.installed_addons[0]))
|
||||
|
||||
def test_install_webextension(self):
|
||||
addon = os.path.join(here, 'addons', 'apply-css.xpi')
|
||||
self.am.install_from_path(addon)
|
||||
self.am.install(addon)
|
||||
self.assertEqual(len(self.am.installed_addons), 1)
|
||||
self.assertTrue(os.path.isfile(self.am.installed_addons[0]))
|
||||
self.assertEqual('apply-css.xpi', os.path.basename(self.am.installed_addons[0]))
|
||||
@ -85,7 +85,7 @@ class TestAddonsManager(unittest.TestCase):
|
||||
|
||||
def test_install_webextension_sans_id(self):
|
||||
addon = os.path.join(here, 'addons', 'apply-css-sans-id.xpi')
|
||||
self.am.install_from_path(addon)
|
||||
self.am.install(addon)
|
||||
|
||||
self.assertEqual(len(self.am.installed_addons), 1)
|
||||
self.assertTrue(os.path.isfile(self.am.installed_addons[0]))
|
||||
@ -94,7 +94,7 @@ class TestAddonsManager(unittest.TestCase):
|
||||
details = self.am.addon_details(self.am.installed_addons[0])
|
||||
self.assertIn('@temporary-addon', details['id'])
|
||||
|
||||
def test_install_from_path_xpi(self):
|
||||
def test_install_xpi(self):
|
||||
addons_to_install = []
|
||||
addons_installed = []
|
||||
|
||||
@ -102,14 +102,14 @@ class TestAddonsManager(unittest.TestCase):
|
||||
for ext in ['test-addon-1@mozilla.org', 'test-addon-2@mozilla.org']:
|
||||
temp_addon = generate_addon(ext, path=self.tmpdir)
|
||||
addons_to_install.append(self.am.addon_details(temp_addon)['id'])
|
||||
self.am.install_from_path(temp_addon)
|
||||
self.am.install(temp_addon)
|
||||
|
||||
# Generate a list of addons installed in the profile
|
||||
addons_installed = [str(x[:-len('.xpi')]) for x in os.listdir(os.path.join(
|
||||
self.profile.profile, 'extensions'))]
|
||||
self.assertEqual(addons_to_install.sort(), addons_installed.sort())
|
||||
|
||||
def test_install_from_path_folder(self):
|
||||
def test_install_folder(self):
|
||||
# Generate installer stubs for all possible types of addons
|
||||
addons = []
|
||||
addons.append(generate_addon('test-addon-1@mozilla.org',
|
||||
@ -126,11 +126,11 @@ class TestAddonsManager(unittest.TestCase):
|
||||
xpi=False))
|
||||
addons.sort()
|
||||
|
||||
self.am.install_from_path(self.tmpdir)
|
||||
self.am.install(self.tmpdir)
|
||||
|
||||
self.assertEqual(self.am.installed_addons, addons)
|
||||
|
||||
def test_install_from_path_unpack(self):
|
||||
def test_install_unpack(self):
|
||||
# Generate installer stubs for all possible types of addons
|
||||
addon_xpi = generate_addon('test-addon-unpack@mozilla.org',
|
||||
path=self.tmpdir)
|
||||
@ -141,34 +141,34 @@ class TestAddonsManager(unittest.TestCase):
|
||||
path=self.tmpdir)
|
||||
|
||||
# Test unpack flag for add-on as XPI
|
||||
self.am.install_from_path(addon_xpi)
|
||||
self.am.install(addon_xpi)
|
||||
self.assertEqual(self.am.installed_addons, [addon_xpi])
|
||||
self.am.clean()
|
||||
|
||||
# Test unpack flag for add-on as folder
|
||||
self.am.install_from_path(addon_folder)
|
||||
self.am.install(addon_folder)
|
||||
self.assertEqual(self.am.installed_addons, [addon_folder])
|
||||
self.am.clean()
|
||||
|
||||
# Test forcing unpack an add-on
|
||||
self.am.install_from_path(addon_no_unpack, unpack=True)
|
||||
self.am.install(addon_no_unpack, unpack=True)
|
||||
self.assertEqual(self.am.installed_addons, [addon_no_unpack])
|
||||
self.am.clean()
|
||||
|
||||
def test_install_from_path_after_reset(self):
|
||||
def test_install_after_reset(self):
|
||||
# Installing the same add-on after a reset should not cause a failure
|
||||
addon = generate_addon('test-addon-1@mozilla.org',
|
||||
path=self.tmpdir, xpi=False)
|
||||
|
||||
# We cannot use self.am because profile.reset() creates a new instance
|
||||
self.profile.addon_manager.install_from_path(addon)
|
||||
self.profile.addons.install(addon)
|
||||
|
||||
self.profile.reset()
|
||||
|
||||
self.profile.addon_manager.install_from_path(addon)
|
||||
self.assertEqual(self.profile.addon_manager.installed_addons, [addon])
|
||||
self.profile.addons.install(addon)
|
||||
self.assertEqual(self.profile.addons.installed_addons, [addon])
|
||||
|
||||
def test_install_from_path_backup(self):
|
||||
def test_install_backup(self):
|
||||
staged_path = os.path.join(self.profile_path, 'extensions')
|
||||
|
||||
# Generate installer stubs for all possible types of addons
|
||||
@ -182,10 +182,10 @@ class TestAddonsManager(unittest.TestCase):
|
||||
name='test-addon-1-dupe@mozilla.org')
|
||||
|
||||
# Test backup of xpi files
|
||||
self.am.install_from_path(addon_xpi)
|
||||
self.am.install(addon_xpi)
|
||||
self.assertIsNone(self.am.backup_dir)
|
||||
|
||||
self.am.install_from_path(addon_xpi)
|
||||
self.am.install(addon_xpi)
|
||||
self.assertIsNotNone(self.am.backup_dir)
|
||||
self.assertEqual(os.listdir(self.am.backup_dir),
|
||||
['test-addon-1@mozilla.org.xpi'])
|
||||
@ -196,10 +196,10 @@ class TestAddonsManager(unittest.TestCase):
|
||||
self.am.clean()
|
||||
|
||||
# Test backup of folders
|
||||
self.am.install_from_path(addon_folder)
|
||||
self.am.install(addon_folder)
|
||||
self.assertIsNone(self.am.backup_dir)
|
||||
|
||||
self.am.install_from_path(addon_folder)
|
||||
self.am.install(addon_folder)
|
||||
self.assertIsNotNone(self.am.backup_dir)
|
||||
self.assertEqual(os.listdir(self.am.backup_dir),
|
||||
['test-addon-1@mozilla.org'])
|
||||
@ -210,10 +210,10 @@ class TestAddonsManager(unittest.TestCase):
|
||||
self.am.clean()
|
||||
|
||||
# Test backup of xpi files with another file name
|
||||
self.am.install_from_path(addon_name)
|
||||
self.am.install(addon_name)
|
||||
self.assertIsNone(self.am.backup_dir)
|
||||
|
||||
self.am.install_from_path(addon_xpi)
|
||||
self.am.install(addon_xpi)
|
||||
self.assertIsNotNone(self.am.backup_dir)
|
||||
self.assertEqual(os.listdir(self.am.backup_dir),
|
||||
['test-addon-1@mozilla.org.xpi'])
|
||||
@ -223,7 +223,7 @@ class TestAddonsManager(unittest.TestCase):
|
||||
['test-addon-1@mozilla.org.xpi'])
|
||||
self.am.clean()
|
||||
|
||||
def test_install_from_path_invalid_addons(self):
|
||||
def test_install_invalid_addons(self):
|
||||
# Generate installer stubs for all possible types of addons
|
||||
addons = []
|
||||
addons.append(generate_addon('test-addon-invalid-no-manifest@mozilla.org',
|
||||
@ -232,17 +232,17 @@ class TestAddonsManager(unittest.TestCase):
|
||||
addons.append(generate_addon('test-addon-invalid-no-id@mozilla.org',
|
||||
path=self.tmpdir))
|
||||
|
||||
self.am.install_from_path(self.tmpdir)
|
||||
self.am.install(self.tmpdir)
|
||||
|
||||
self.assertEqual(self.am.installed_addons, [])
|
||||
|
||||
@unittest.skip("Feature not implemented as part of AddonManger")
|
||||
def test_install_from_path_error(self):
|
||||
""" Check install_from_path raises an error with an invalid addon"""
|
||||
def test_install_error(self):
|
||||
""" Check install raises an error with an invalid addon"""
|
||||
|
||||
temp_addon = generate_addon('test-addon-invalid-version@mozilla.org')
|
||||
# This should raise an error here
|
||||
self.am.install_from_path(temp_addon)
|
||||
self.am.install(temp_addon)
|
||||
|
||||
def test_addon_details(self):
|
||||
# Generate installer stubs for a valid and invalid add-on manifest
|
||||
@ -276,7 +276,7 @@ class TestAddonsManager(unittest.TestCase):
|
||||
addon_one = generate_addon('test-addon-1@mozilla.org')
|
||||
addon_two = generate_addon('test-addon-2@mozilla.org')
|
||||
|
||||
self.am.install_addons(addon_one)
|
||||
self.am.install(addon_one)
|
||||
installed_addons = [str(x[:-len('.xpi')]) for x in os.listdir(os.path.join(
|
||||
self.profile.profile, 'extensions'))]
|
||||
|
||||
@ -285,7 +285,7 @@ class TestAddonsManager(unittest.TestCase):
|
||||
# Cleanup addons
|
||||
duplicate_profile = mozprofile.profile.Profile(profile=self.profile.profile,
|
||||
addons=addon_two)
|
||||
duplicate_profile.addon_manager.clean()
|
||||
duplicate_profile.addons.clean()
|
||||
|
||||
addons_after_cleanup = [str(x[:-len('.xpi')]) for x in os.listdir(os.path.join(
|
||||
duplicate_profile.profile, 'extensions'))]
|
||||
@ -311,7 +311,7 @@ class TestAddonsManager(unittest.TestCase):
|
||||
am = mozprofile.addons.AddonManager(profile, restore=True)
|
||||
|
||||
for addon in addons:
|
||||
am.install_from_path(addon)
|
||||
am.install(addon)
|
||||
|
||||
# now its there
|
||||
self.assertEqual(os.listdir(profile), ['extensions'])
|
||||
@ -335,7 +335,7 @@ class TestAddonsManager(unittest.TestCase):
|
||||
addons.append(generate_addon('test-addon-2@mozilla.org',
|
||||
path=self.tmpdir))
|
||||
|
||||
self.am.install_from_path(self.tmpdir)
|
||||
self.am.install(self.tmpdir)
|
||||
|
||||
extensions_path = os.path.join(self.profile_path, 'extensions')
|
||||
staging_path = os.path.join(extensions_path)
|
||||
|
@ -125,7 +125,7 @@ class FFSetup(object):
|
||||
# installing addons
|
||||
LOG.info("Installing Add-ons:")
|
||||
LOG.info(extensions)
|
||||
profile.addon_manager.install_addons(extensions)
|
||||
profile.addons.install(extensions)
|
||||
|
||||
# installing webextensions
|
||||
webextensions = self.test_config.get('webextensions', None)
|
||||
@ -143,7 +143,7 @@ class FFSetup(object):
|
||||
if not os.path.exists(filename):
|
||||
continue
|
||||
LOG.info(filename)
|
||||
profile.addon_manager.install_from_path(filename)
|
||||
profile.addons.install(filename)
|
||||
|
||||
def _run_profile(self):
|
||||
runner_cls = mozrunner.runners.get(
|
||||
|
Loading…
Reference in New Issue
Block a user