Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 #!/usr/bin/env python
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/.
7 import os
8 import shutil
9 import tempfile
10 import unittest
11 import urllib2
13 from manifestparser import ManifestParser
14 import mozfile
15 import mozhttpd
16 import mozlog
17 import mozprofile
19 from addon_stubs import generate_addon, generate_manifest
22 here = os.path.dirname(os.path.abspath(__file__))
25 class TestAddonsManager(unittest.TestCase):
26 """ Class to test mozprofile.addons.AddonManager """
28 def setUp(self):
29 self.logger = mozlog.getLogger('mozprofile.addons')
30 self.logger.setLevel(mozlog.ERROR)
32 self.profile = mozprofile.profile.Profile()
33 self.am = self.profile.addon_manager
35 self.profile_path = self.profile.profile
36 self.tmpdir = tempfile.mkdtemp()
38 def tearDown(self):
39 mozfile.rmtree(self.tmpdir)
41 self.am = None
42 self.profile = None
44 # Bug 934484
45 # Sometimes the profile folder gets recreated at the end and will be left
46 # behind. So we should ensure that we clean it up correctly.
47 mozfile.rmtree(self.profile_path)
49 def test_install_addons_multiple_same_source(self):
50 # Generate installer stubs for all possible types of addons
51 addon_xpi = generate_addon('test-addon-1@mozilla.org',
52 path=self.tmpdir)
53 addon_folder = generate_addon('test-addon-1@mozilla.org',
54 path=self.tmpdir,
55 xpi=False)
57 # The same folder should not be installed twice
58 self.am.install_addons([addon_folder, addon_folder])
59 self.assertEqual(self.am.installed_addons, [addon_folder])
60 self.am.clean()
62 # The same XPI file should not be installed twice
63 self.am.install_addons([addon_xpi, addon_xpi])
64 self.assertEqual(self.am.installed_addons, [addon_xpi])
65 self.am.clean()
67 # Even if it is the same id the add-on should be installed twice, if
68 # specified via XPI and folder
69 self.am.install_addons([addon_folder, addon_xpi])
70 self.assertEqual(len(self.am.installed_addons), 2)
71 self.assertIn(addon_folder, self.am.installed_addons)
72 self.assertIn(addon_xpi, self.am.installed_addons)
73 self.am.clean()
75 def test_download(self):
76 server = mozhttpd.MozHttpd(docroot=os.path.join(here, 'addons'))
77 server.start()
79 # Download a valid add-on without a class instance to the general
80 # tmp folder and clean-up
81 try:
82 addon = server.get_url() + 'empty.xpi'
83 xpi_file = mozprofile.addons.AddonManager.download(addon)
84 self.assertTrue(os.path.isfile(xpi_file))
85 self.assertIn('test-empty@quality.mozilla.org.xpi',
86 os.path.basename(xpi_file))
87 self.assertNotIn(self.tmpdir, os.path.dirname(xpi_file))
88 finally:
89 # Given that the file is stored outside of the created tmp dir
90 # we have to ensure to explicitely remove it
91 if os.path.isfile(xpi_file):
92 os.remove(xpi_file)
94 # Download an valid add-on to a special folder
95 addon = server.get_url() + 'empty.xpi'
96 xpi_file = self.am.download(addon, self.tmpdir)
97 self.assertTrue(os.path.isfile(xpi_file))
98 self.assertIn('test-empty@quality.mozilla.org.xpi',
99 os.path.basename(xpi_file))
100 self.assertIn(self.tmpdir, os.path.dirname(xpi_file))
101 self.assertEqual(self.am.downloaded_addons, [])
102 os.remove(xpi_file)
104 # Download an invalid add-on to a special folder
105 addon = server.get_url() + 'invalid.xpi'
106 self.assertRaises(mozprofile.addons.AddonFormatError,
107 self.am.download, addon, self.tmpdir)
108 self.assertEqual(os.listdir(self.tmpdir), [])
110 # Download from an invalid URL
111 addon = server.get_url() + 'not_existent.xpi'
112 self.assertRaises(urllib2.HTTPError,
113 self.am.download, addon, self.tmpdir)
114 self.assertEqual(os.listdir(self.tmpdir), [])
116 # Download from an invalid URL
117 addon = 'not_existent.xpi'
118 self.assertRaises(ValueError,
119 self.am.download, addon, self.tmpdir)
120 self.assertEqual(os.listdir(self.tmpdir), [])
122 server.stop()
124 def test_install_from_path_xpi(self):
125 addons_to_install = []
126 addons_installed = []
128 # Generate installer stubs and install them
129 for ext in ['test-addon-1@mozilla.org', 'test-addon-2@mozilla.org']:
130 temp_addon = generate_addon(ext, path=self.tmpdir)
131 addons_to_install.append(self.am.addon_details(temp_addon)['id'])
132 self.am.install_from_path(temp_addon)
134 # Generate a list of addons installed in the profile
135 addons_installed = [unicode(x[:-len('.xpi')]) for x in os.listdir(os.path.join(
136 self.profile.profile, 'extensions', 'staged'))]
137 self.assertEqual(addons_to_install.sort(), addons_installed.sort())
139 def test_install_from_path_folder(self):
140 # Generate installer stubs for all possible types of addons
141 addons = []
142 addons.append(generate_addon('test-addon-1@mozilla.org',
143 path=self.tmpdir))
144 addons.append(generate_addon('test-addon-2@mozilla.org',
145 path=self.tmpdir,
146 xpi=False))
147 addons.append(generate_addon('test-addon-3@mozilla.org',
148 path=self.tmpdir,
149 name='addon-3'))
150 addons.append(generate_addon('test-addon-4@mozilla.org',
151 path=self.tmpdir,
152 name='addon-4',
153 xpi=False))
154 addons.sort()
156 self.am.install_from_path(self.tmpdir)
158 self.assertEqual(self.am.installed_addons, addons)
160 def test_install_from_path_unpack(self):
161 # Generate installer stubs for all possible types of addons
162 addon_xpi = generate_addon('test-addon-unpack@mozilla.org',
163 path=self.tmpdir)
164 addon_folder = generate_addon('test-addon-unpack@mozilla.org',
165 path=self.tmpdir,
166 xpi=False)
167 addon_no_unpack = generate_addon('test-addon-1@mozilla.org',
168 path=self.tmpdir)
170 # Test unpack flag for add-on as XPI
171 self.am.install_from_path(addon_xpi)
172 self.assertEqual(self.am.installed_addons, [addon_xpi])
173 self.am.clean()
175 # Test unpack flag for add-on as folder
176 self.am.install_from_path(addon_folder)
177 self.assertEqual(self.am.installed_addons, [addon_folder])
178 self.am.clean()
180 # Test forcing unpack an add-on
181 self.am.install_from_path(addon_no_unpack, unpack=True)
182 self.assertEqual(self.am.installed_addons, [addon_no_unpack])
183 self.am.clean()
185 def test_install_from_path_url(self):
186 server = mozhttpd.MozHttpd(docroot=os.path.join(here, 'addons'))
187 server.start()
189 addon = server.get_url() + 'empty.xpi'
190 self.am.install_from_path(addon)
192 server.stop()
194 self.assertEqual(len(self.am.downloaded_addons), 1)
195 self.assertTrue(os.path.isfile(self.am.downloaded_addons[0]))
196 self.assertIn('test-empty@quality.mozilla.org.xpi',
197 os.path.basename(self.am.downloaded_addons[0]))
199 def test_install_from_path_after_reset(self):
200 # Installing the same add-on after a reset should not cause a failure
201 addon = generate_addon('test-addon-1@mozilla.org',
202 path=self.tmpdir, xpi=False)
204 # We cannot use self.am because profile.reset() creates a new instance
205 self.profile.addon_manager.install_from_path(addon)
207 self.profile.reset()
209 self.profile.addon_manager.install_from_path(addon)
210 self.assertEqual(self.profile.addon_manager.installed_addons, [addon])
212 def test_install_from_path_backup(self):
213 staged_path = os.path.join(self.profile_path, 'extensions', 'staged')
215 # Generate installer stubs for all possible types of addons
216 addon_xpi = generate_addon('test-addon-1@mozilla.org',
217 path=self.tmpdir)
218 addon_folder = generate_addon('test-addon-1@mozilla.org',
219 path=self.tmpdir,
220 xpi=False)
221 addon_name = generate_addon('test-addon-1@mozilla.org',
222 path=self.tmpdir,
223 name='test-addon-1-dupe@mozilla.org')
225 # Test backup of xpi files
226 self.am.install_from_path(addon_xpi)
227 self.assertIsNone(self.am.backup_dir)
229 self.am.install_from_path(addon_xpi)
230 self.assertIsNotNone(self.am.backup_dir)
231 self.assertEqual(os.listdir(self.am.backup_dir),
232 ['test-addon-1@mozilla.org.xpi'])
234 self.am.clean()
235 self.assertEqual(os.listdir(staged_path),
236 ['test-addon-1@mozilla.org.xpi'])
237 self.am.clean()
239 # Test backup of folders
240 self.am.install_from_path(addon_folder)
241 self.assertIsNone(self.am.backup_dir)
243 self.am.install_from_path(addon_folder)
244 self.assertIsNotNone(self.am.backup_dir)
245 self.assertEqual(os.listdir(self.am.backup_dir),
246 ['test-addon-1@mozilla.org'])
248 self.am.clean()
249 self.assertEqual(os.listdir(staged_path),
250 ['test-addon-1@mozilla.org'])
251 self.am.clean()
253 # Test backup of xpi files with another file name
254 self.am.install_from_path(addon_name)
255 self.assertIsNone(self.am.backup_dir)
257 self.am.install_from_path(addon_xpi)
258 self.assertIsNotNone(self.am.backup_dir)
259 self.assertEqual(os.listdir(self.am.backup_dir),
260 ['test-addon-1@mozilla.org.xpi'])
262 self.am.clean()
263 self.assertEqual(os.listdir(staged_path),
264 ['test-addon-1@mozilla.org.xpi'])
265 self.am.clean()
267 def test_install_from_path_invalid_addons(self):
268 # Generate installer stubs for all possible types of addons
269 addons = []
270 addons.append(generate_addon('test-addon-invalid-no-manifest@mozilla.org',
271 path=self.tmpdir,
272 xpi=False))
273 addons.append(generate_addon('test-addon-invalid-no-id@mozilla.org',
274 path=self.tmpdir))
276 self.am.install_from_path(self.tmpdir)
278 self.assertEqual(self.am.installed_addons, [])
280 @unittest.skip("Feature not implemented as part of AddonManger")
281 def test_install_from_path_error(self):
282 """ Check install_from_path raises an error with an invalid addon"""
284 temp_addon = generate_addon('test-addon-invalid-version@mozilla.org')
285 # This should raise an error here
286 self.am.install_from_path(temp_addon)
288 def test_install_from_manifest(self):
289 temp_manifest = generate_manifest(['test-addon-1@mozilla.org',
290 'test-addon-2@mozilla.org'])
291 m = ManifestParser()
292 m.read(temp_manifest)
293 addons = m.get()
295 # Obtain details of addons to install from the manifest
296 addons_to_install = [self.am.addon_details(x['path']).get('id') for x in addons]
298 self.am.install_from_manifest(temp_manifest)
299 # Generate a list of addons installed in the profile
300 addons_installed = [unicode(x[:-len('.xpi')]) for x in os.listdir(os.path.join(
301 self.profile.profile, 'extensions', 'staged'))]
302 self.assertEqual(addons_installed.sort(), addons_to_install.sort())
304 # Cleanup the temporary addon and manifest directories
305 mozfile.rmtree(os.path.dirname(temp_manifest))
307 def test_addon_details(self):
308 # Generate installer stubs for a valid and invalid add-on manifest
309 valid_addon = generate_addon('test-addon-1@mozilla.org',
310 path=self.tmpdir)
311 invalid_addon = generate_addon('test-addon-invalid-not-wellformed@mozilla.org',
312 path=self.tmpdir)
314 # Check valid add-on
315 details = self.am.addon_details(valid_addon)
316 self.assertEqual(details['id'], 'test-addon-1@mozilla.org')
317 self.assertEqual(details['name'], 'Test Add-on 1')
318 self.assertEqual(details['unpack'], False)
319 self.assertEqual(details['version'], '0.1')
321 # Check invalid add-on
322 self.assertRaises(mozprofile.addons.AddonFormatError,
323 self.am.addon_details, invalid_addon)
325 # Check invalid path
326 self.assertRaises(IOError,
327 self.am.addon_details, '')
329 # Check invalid add-on format
330 addon_path = os.path.join(os.path.join(here, 'files'), 'not_an_addon.txt')
331 self.assertRaises(mozprofile.addons.AddonFormatError,
332 self.am.addon_details, addon_path)
334 @unittest.skip("Bug 900154")
335 def test_clean_addons(self):
336 addon_one = generate_addon('test-addon-1@mozilla.org')
337 addon_two = generate_addon('test-addon-2@mozilla.org')
339 self.am.install_addons(addon_one)
340 installed_addons = [unicode(x[:-len('.xpi')]) for x in os.listdir(os.path.join(
341 self.profile.profile, 'extensions', 'staged'))]
343 # Create a new profile based on an existing profile
344 # Install an extra addon in the new profile
345 # Cleanup addons
346 duplicate_profile = mozprofile.profile.Profile(profile=self.profile.profile,
347 addons=addon_two)
348 duplicate_profile.addon_manager.clean()
350 addons_after_cleanup = [unicode(x[:-len('.xpi')]) for x in os.listdir(os.path.join(
351 duplicate_profile.profile, 'extensions', 'staged'))]
352 # New addons installed should be removed by clean_addons()
353 self.assertEqual(installed_addons, addons_after_cleanup)
355 def test_noclean(self):
356 """test `restore=True/False` functionality"""
358 server = mozhttpd.MozHttpd(docroot=os.path.join(here, 'addons'))
359 server.start()
361 profile = tempfile.mkdtemp()
362 tmpdir = tempfile.mkdtemp()
364 try:
365 # empty initially
366 self.assertFalse(bool(os.listdir(profile)))
368 # make an addon
369 addons = []
370 addons.append(generate_addon('test-addon-1@mozilla.org',
371 path=tmpdir))
372 addons.append(server.get_url() + 'empty.xpi')
374 # install it with a restore=True AddonManager
375 am = mozprofile.addons.AddonManager(profile, restore=True)
377 for addon in addons:
378 am.install_from_path(addon)
380 # now its there
381 self.assertEqual(os.listdir(profile), ['extensions'])
382 staging_folder = os.path.join(profile, 'extensions', 'staged')
383 self.assertTrue(os.path.exists(staging_folder))
384 self.assertEqual(len(os.listdir(staging_folder)), 2)
386 # del addons; now its gone though the directory tree exists
387 downloaded_addons = am.downloaded_addons
388 del am
390 self.assertEqual(os.listdir(profile), ['extensions'])
391 self.assertTrue(os.path.exists(staging_folder))
392 self.assertEqual(os.listdir(staging_folder), [])
394 for addon in downloaded_addons:
395 self.assertFalse(os.path.isfile(addon))
397 finally:
398 mozfile.rmtree(tmpdir)
399 mozfile.rmtree(profile)
401 def test_remove_addon(self):
402 addons = []
403 addons.append(generate_addon('test-addon-1@mozilla.org',
404 path=self.tmpdir))
405 addons.append(generate_addon('test-addon-2@mozilla.org',
406 path=self.tmpdir))
408 self.am.install_from_path(self.tmpdir)
410 extensions_path = os.path.join(self.profile_path, 'extensions')
411 staging_path = os.path.join(extensions_path, 'staged')
413 # Fake a run by virtually installing one of the staged add-ons
414 shutil.move(os.path.join(staging_path, 'test-addon-1@mozilla.org.xpi'),
415 extensions_path)
417 for addon in self.am._addons:
418 self.am.remove_addon(addon)
420 self.assertEqual(os.listdir(staging_path), [])
421 self.assertEqual(os.listdir(extensions_path), ['staged'])
424 if __name__ == '__main__':
425 unittest.main()