Bug 1479599 Recognize webextensions in packager draft
authorAndrew Swan <aswan@mozilla.com>
Tue, 31 Jul 2018 21:51:02 -0700
changeset 827282 2877f558a2a0632383eebdbf067458123fff84f2
parent 824607 0d72c7996d60a7c07e35c5f90d78b02a47d17460
push id118505
push useraswan@mozilla.com
push dateTue, 07 Aug 2018 16:44:08 +0000
bugs1479599
milestone63.0a1
Bug 1479599 Recognize webextensions in packager MozReview-Commit-ID: KethvfCTf6G
python/mozbuild/mozpack/packager/__init__.py
python/mozbuild/mozpack/test/test_packager.py
--- a/python/mozbuild/mozpack/packager/__init__.py
+++ b/python/mozbuild/mozpack/packager/__init__.py
@@ -13,16 +13,17 @@ from mozpack.chrome.manifest import (
     ManifestBinaryComponent,
     ManifestChrome,
     ManifestInterfaces,
     is_manifest,
     parse_manifest,
 )
 import mozpack.path as mozpath
 from collections import deque
+import json
 
 
 class Component(object):
     '''
     Class that represents a component in a package manifest.
     '''
     def __init__(self, name, destdir=''):
         if name.find(' ') > 0:
@@ -264,17 +265,40 @@ class SimplePackager(object):
             self._queue.append(self.formatter.add_interfaces, path, file)
         else:
             self._file_queue.append(self.formatter.add, path, file)
             if mozpath.basename(path) == 'install.rdf':
                 addon = True
                 install_rdf = file.open().read()
                 if self.UNPACK_ADDON_RE.search(install_rdf):
                     addon = 'unpacked'
-                self._addons[mozpath.dirname(path)] = addon
+                self._add_addon(mozpath.dirname(path), addon)
+            elif mozpath.basename(path) == 'manifest.json':
+                manifest = file.open().read()
+                try:
+                    parsed = json.loads(manifest)
+                except ValueError:
+                    pass
+                if isinstance(parsed, dict) and parsed.has_key('manifest_version'):
+                    self._add_addon(mozpath.dirname(path), True)
+
+    def _add_addon(self, path, addon_type):
+        '''
+        Add the given BaseFile to the collection of addons if a parent
+        directory is not already in the collection.
+        '''
+        if mozpath.basedir(path, self._addons) != None:
+            return
+
+        for dir in self._addons:
+            if mozpath.basedir(dir, [path]) != None:
+                del self._addons[dir]
+                break
+
+        self._addons[path] = addon_type
 
     def _add_manifest_file(self, path, file):
         '''
         Add the given BaseFile with manifest file contents with the given path.
         '''
         self._manifests.add(path)
         base = ''
         if hasattr(file, 'path'):
--- a/python/mozbuild/mozpack/test/test_packager.py
+++ b/python/mozbuild/mozpack/test/test_packager.py
@@ -232,16 +232,39 @@ class TestSimplePackager(unittest.TestCa
                 '<RDF>\n<... em:unpack=\'true\'>\n<...>\n</RDF>')
             packager.add('addon10/install.rdf', install_rdf_addon10)
 
         with errors.context('manifest', 19):
             install_rdf_addon11 = GeneratedFile(
                 '<RDF>\n<... em:unpack=\'false\'>\n<...>\n</RDF>')
             packager.add('addon11/install.rdf', install_rdf_addon11)
 
+        we_manifest = GeneratedFile('{"manifest_version": 2, "name": "Test WebExtension", "version": "1.0"}')
+        # hybrid and hybrid2 are both bootstrapped extensions with
+        # embedded webextensions, they differ in the order in which
+        # the manifests are added to the packager.
+        with errors.context('manifest', 20):
+            packager.add('hybrid/install.rdf', install_rdf)
+
+        with errors.context('manifest', 21):
+            packager.add('hybrid/webextension/manifest.json', we_manifest)
+
+        with errors.context('manifest', 22):
+            packager.add('hybrid2/webextension/manifest.json', we_manifest)
+
+        with errors.context('manifest', 23):
+            packager.add('hybrid2/install.rdf', install_rdf)
+
+        with errors.context('manifest', 24):
+            packager.add('webextension/manifest.json', we_manifest)
+
+        non_we_manifest = GeneratedFile('{"not a webextension": true}')
+        with errors.context('manifest', 25):
+            packager.add('nonwebextension/manifest.json', non_we_manifest)
+
         self.assertEqual(formatter.log, [])
 
         with errors.context('dummy', 1):
             packager.close()
         self.maxDiff = None
         # The formatter is expected to reorder the manifest entries so that
         # chrome entries appear before the others.
         self.assertEqual(formatter.log, [
@@ -252,17 +275,20 @@ class TestSimplePackager(unittest.TestCa
             (('dummy', 1), 'add_base', 'addon2', 'unpacked'),
             (('dummy', 1), 'add_base', 'addon3', 'unpacked'),
             (('dummy', 1), 'add_base', 'addon4', 'unpacked'),
             (('dummy', 1), 'add_base', 'addon5', True),
             (('dummy', 1), 'add_base', 'addon6', 'unpacked'),
             (('dummy', 1), 'add_base', 'addon7', True),
             (('dummy', 1), 'add_base', 'addon8', 'unpacked'),
             (('dummy', 1), 'add_base', 'addon9', True),
+            (('dummy', 1), 'add_base', 'hybrid', True),
+            (('dummy', 1), 'add_base', 'hybrid2', True),
             (('dummy', 1), 'add_base', 'qux', False),
+            (('dummy', 1), 'add_base', 'webextension', True),
             ((os.path.join(curdir, 'foo', 'bar.manifest'), 2),
              'add_manifest', ManifestContent('foo', 'bar', 'bar/')),
             ((os.path.join(curdir, 'foo', 'bar.manifest'), 1),
              'add_manifest', ManifestResource('foo', 'bar', 'bar/')),
             (('bar/baz.manifest', 1),
              'add_manifest', ManifestResource('bar', 'baz', 'baz/')),
             (('qux/qux.manifest', 1),
              'add_manifest', ManifestResource('qux', 'qux', 'qux/')),
@@ -292,22 +318,33 @@ class TestSimplePackager(unittest.TestCa
             (('manifest', 16), 'add', 'addon8/install.rdf',
              install_rdf_addon8),
             (('manifest', 17), 'add', 'addon9/install.rdf',
              install_rdf_addon9),
             (('manifest', 18), 'add', 'addon10/install.rdf',
              install_rdf_addon10),
             (('manifest', 19), 'add', 'addon11/install.rdf',
              install_rdf_addon11),
+            (('manifest', 20), 'add', 'hybrid/install.rdf', install_rdf),
+            (('manifest', 21),
+             'add', 'hybrid/webextension/manifest.json', we_manifest),
+            (('manifest', 22),
+             'add', 'hybrid2/webextension/manifest.json', we_manifest),
+            (('manifest', 23), 'add', 'hybrid2/install.rdf', install_rdf),
+            (('manifest', 24),
+             'add', 'webextension/manifest.json', we_manifest),
+            (('manifest', 25),
+             'add', 'nonwebextension/manifest.json', non_we_manifest),
         ])
 
         self.assertEqual(packager.get_bases(),
                          set(['', 'addon', 'addon2', 'addon3', 'addon4',
                               'addon5', 'addon6', 'addon7', 'addon8',
-                              'addon9', 'addon10', 'addon11', 'qux']))
+                              'addon9', 'addon10', 'addon11', 'qux',
+                              'hybrid', 'hybrid2', 'webextension']))
         self.assertEqual(packager.get_bases(addons=False), set(['', 'qux']))
 
     def test_simple_packager_manifest_consistency(self):
         formatter = MockFormatter()
         # bar/ is detected as an addon because of install.rdf, but top-level
         # includes a manifest inside bar/.
         packager = SimplePackager(formatter)
         packager.add('base.manifest', GeneratedFile(