Skip to content
This repository has been archived by the owner on Aug 20, 2018. It is now read-only.

Commit

Permalink
Bug 931188 - [mozprofile] AddonManager fails in iterating over add-on…
Browse files Browse the repository at this point in the history
…s (.xpi) inside a folder. r=jhammel
  • Loading branch information
whimboo committed Oct 29, 2013
1 parent eda1c03 commit 12303c6
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 91 deletions.
22 changes: 19 additions & 3 deletions mozprofile/mozprofile/addons.py
Expand Up @@ -11,9 +11,11 @@
from manifestparser import ManifestParser
from xml.dom import minidom


# Needed for the AMO's rest API - https://developer.mozilla.org/en/addons.mozilla.org_%28AMO%29_API_Developers%27_Guide/The_generic_AMO_API
AMO_API_VERSION = "1.5"


class AddonManager(object):
"""
Handles all operations regarding addons in a profile including:
Expand All @@ -39,6 +41,18 @@ def __init__(self, profile, restore=True):
# backup dir for already existing addons
self.backup_dir = None

def is_addon(self, addon_path):
"""
Checks if the given path is a valid addon
:param addon_path: path to the add-on directory or XPI
"""
try:
details = self.addon_details(addon_path)
return details.get('id') is not None
except:
return False

def install_addons(self, addons=None, manifests=None):
"""
Installs all types of addons
Expand Down Expand Up @@ -187,14 +201,16 @@ def install_from_path(self, path, unpack=False):
else:
tmpfile = None

# if the addon is a directory, install all addons in it
addons = [path]
if not path.endswith('.xpi') and not os.path.exists(os.path.join(path, 'install.rdf')):

# if path is not an add-on, try to install all contained add-ons
if not self.is_addon(path):
# 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
os.path.isdir(os.path.join(path, x))]
self.is_addon(os.path.join(path, x))]
addons.sort()

# install each addon
for addon in addons:
Expand Down
89 changes: 41 additions & 48 deletions mozprofile/tests/addon_stubs.py
@@ -1,84 +1,77 @@
#!/usr/bin/env python

import tempfile
import mozhttpd
import os
import tempfile
import zipfile

import mozfile
import mozhttpd


here = os.path.dirname(os.path.abspath(__file__))

# stubs is a dict of the form {'addon name': 'install manifest content'}
# stubs is a dict of the form {'addon id': 'install manifest content'}
stubs = {
'empty-0-1.xpi':
open(os.path.join(here, "install_manifests", "empty-0-1.rdf"), 'r').read(),
'empty-0-2.xpi':
open(os.path.join(here, "install_manifests", "empty-0-2.rdf"), 'r').read(),
'another-empty-0-1.xpi':
open(os.path.join(here, "install_manifests", "another-empty-0-1.rdf"), 'r').read(),
'empty-invalid.xpi':
open(os.path.join(here, "install_manifests", "empty-invalid.rdf"), 'r').read()}

def generate_addon(name, path=None):
'test-addon-1@mozilla.org': 'test_addon_1.rdf',
'test-addon-2@mozilla.org': 'test_addon_2.rdf',
'test-addon-3@mozilla.org': 'test_addon_3.rdf',
'test-addon-4@mozilla.org': 'test_addon_4.rdf',
'test-addon-invalid-no-id@mozilla.org': 'test_addon_invalid_no_id.rdf',
'test-addon-invalid-version@mozilla.org': 'test_addon_invalid_version.rdf',
'test-addon-invalid-no-manifest@mozilla.org': None,}


def generate_addon(addon_id, path=None, name=None, xpi=True):
"""
Method to generate a single addon.
:param name: name of an addon to generate from the stubs dictionary
:param addon_id: id of an addon to generate from the stubs dictionary
:param path: path where addon and .xpi should be generated
:param name: name for the addon folder or .xpi file
:param xpi: Flag if an XPI or folder should be generated
Returns the file-path of the addon's .xpi file
"""

if name in stubs.keys():
addon = name
else:
# If `name` is not in listed stubs, raise exception
raise IOError('Requested addon stub does not exist')
if not addon_id in stubs.keys():
raise IOError('Requested addon stub "%s" does not exist' % addon_id)

# Generate directory structure for addon
try:
if path:
tmpdir = path
else:
tmpdir = tempfile.mkdtemp()
addon_dir = os.path.join(tmpdir, addon[:-4])
tmpdir = path or tempfile.mkdtemp()
addon_dir = os.path.join(tmpdir, name or addon_id)
os.mkdir(addon_dir)
install_rdf = os.path.join(addon_dir, 'install.rdf')
xpi = os.path.join(tmpdir, addon)
except IOError:
raise IOError('Could not generate directory structure for addon stub.')

# Write install.rdf for addon
with open(install_rdf, 'w') as f:
f.write(stubs[addon])
# Generate the .xpi for the addon
with zipfile.ZipFile(xpi, 'w') as x:
x.write(install_rdf, install_rdf[len(addon_dir):])
if stubs[addon_id]:
install_rdf = os.path.join(addon_dir, 'install.rdf')
with open(install_rdf, 'w') as f:
manifest = os.path.join(here, 'install_manifests', stubs[addon_id])
f.write(open(manifest, 'r').read())

return xpi
if not xpi:
return addon_dir

def generate_invalid_addon(path=None):
"""
Method to create an invalid addon
# Generate the .xpi for the addon
xpi_file = os.path.join(tmpdir, (name or addon_id) + '.xpi')
with zipfile.ZipFile(xpi_file, 'w') as x:
x.write(install_rdf, install_rdf[len(addon_dir):])

Returns the file-path to the .xpi of an invalid addon
"""
return generate_addon(name='empty-invalid.xpi', path=path)
# Ensure we remove the temporary folder to not install the addon twice
mozfile.rmtree(addon_dir)

def generate_manifest(path=None):
return xpi_file

if path:
tmpdir = path
else:
tmpdir = tempfile.mkdtemp()

addon_list = ['empty-0-1.xpi', 'another-empty-0-1.xpi']
for a in addon_list:
generate_addon(a, tmpdir)
def generate_manifest(addon_list, path=None):
tmpdir = path or tempfile.mkdtemp()
addons = [generate_addon(addon, path=tmpdir) for addon in addon_list]

manifest = os.path.join(tmpdir, 'manifest.ini')
with open(manifest, 'w') as f:
for a in addon_list:
f.write('[' + a + ']\n')
for addon in addons:
f.write('[' + addon + ']\n')

return manifest
Expand Up @@ -2,11 +2,11 @@
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>test-empty@quality.mozilla.org</em:id>
<em:id>test-addon-1@mozilla.org</em:id>
<em:version>0.1</em:version>
<em:name>Test Extension (empty)</em:name>
<em:creator>Mozilla QA</em:creator>
<em:homepageURL>http://quality.mozilla.org</em:homepageURL>
<em:name>Test Add-on 1</em:name>
<em:creator>Mozilla</em:creator>
<em:homepageURL>http://mozilla.org</em:homepageURL>
<em:type>2</em:type>

<!-- Firefox -->
Expand Down
Expand Up @@ -2,11 +2,11 @@
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>test-empty@quality.mozilla.org</em:id>
<em:id>test-addon-2@mozilla.org</em:id>
<em:version>0.2</em:version>
<em:name>Test Extension (empty)</em:name>
<em:creator>Mozilla QA</em:creator>
<em:homepageURL>http://quality.mozilla.org</em:homepageURL>
<em:name>Test Add-on 2</em:name>
<em:creator>Mozilla</em:creator>
<em:homepageURL>http://mozilla.org</em:homepageURL>
<em:type>2</em:type>

<!-- Firefox -->
Expand Down
Expand Up @@ -2,11 +2,11 @@
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>another-test-empty@quality.mozilla.org</em:id>
<em:id>test-addon-3@mozilla.org</em:id>
<em:version>0.1</em:version>
<em:name>Another Test Extension (empty)</em:name>
<em:creator>Mozilla QA</em:creator>
<em:homepageURL>http://quality.mozilla.org</em:homepageURL>
<em:name>Test Add-on 3</em:name>
<em:creator>Mozilla</em:creator>
<em:homepageURL>http://mozilla.org</em:homepageURL>
<em:type>2</em:type>

<!-- Firefox -->
Expand Down
22 changes: 22 additions & 0 deletions mozprofile/tests/install_manifests/test_addon_4.rdf
@@ -0,0 +1,22 @@
<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>test-addon-4@mozilla.org</em:id>
<em:version>0.1</em:version>
<em:name>Test Add-on 4</em:name>
<em:creator>Mozilla</em:creator>
<em:homepageURL>http://mozilla.org</em:homepageURL>
<em:type>2</em:type>

<!-- Firefox -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>3.5.*</em:minVersion>
<em:maxVersion>*</em:maxVersion>
</Description>
</em:targetApplication>
</Description>
</RDF>

22 changes: 22 additions & 0 deletions mozprofile/tests/install_manifests/test_addon_invalid_no_id.rdf
@@ -0,0 +1,22 @@
<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<!-- Invalid because of a missing add-on id -->
<em:version>0.1</em:version>
<em:name>Test Invalid Extension (no id)</em:name>
<em:creator>Mozilla</em:creator>
<em:homepageURL>http://mozilla.org</em:homepageURL>
<em:type>2</em:type>

<!-- Firefox -->
<em:targetApplication>
<Description>
<!-- Invalid target application string -->
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>3.5.*</em:minVersion>
<em:maxVersion>*</em:maxVersion>
</Description>
</em:targetApplication>
</Description>
</RDF>
Expand Up @@ -2,12 +2,12 @@
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>test-empty@quality.mozilla.org</em:id>
<!-- Invalid plugin version -->
<em:id>test-addon-invalid-version@mozilla.org</em:id>
<!-- Invalid addon version -->
<em:version>0.NOPE</em:version>
<em:name>Test Extension (empty)</em:name>
<em:creator>Mozilla QA</em:creator>
<em:homepageURL>http://quality.mozilla.org</em:homepageURL>
<em:name>Test Invalid Extension (invalid version)</em:name>
<em:creator>Mozilla</em:creator>
<em:homepageURL>http://mozilla.org</em:homepageURL>
<em:type>2</em:type>

<!-- Firefox -->
Expand Down

0 comments on commit 12303c6

Please sign in to comment.