Bug 1449055 Make browser_all_files_referenced.js work with formautofill as a webextension r=florian
☠☠ backed out by 9b421c484e49 ☠ ☠
authorAndrew Swan <aswan@mozilla.com>
Wed, 01 Aug 2018 18:22:23 -0700
changeset 486877 fc97f5b5e65d6dfaac3cf618c7b87e11d5186d4d
parent 486876 45306ff933fe8dfad0ab11b2f4072389b15fd993
child 486878 89c9c6ba40fd1f8819d9855433d97e5086bb74d2
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersflorian
bugs1449055
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1449055 Make browser_all_files_referenced.js work with formautofill as a webextension r=florian MozReview-Commit-ID: JV3vA8bmDWt
browser/base/content/test/static/browser_all_files_referenced.js
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -239,23 +239,33 @@ trackResourcePrefix("app");
 
 function getBaseUriForChromeUri(chromeUri) {
   let chromeFile = chromeUri + "gobbledygooknonexistentfile.reallynothere";
   let uri = Services.io.newURI(chromeFile);
   let fileUri = gChromeReg.convertChromeURL(uri);
   return fileUri.resolve(".");
 }
 
+function trackChromeUri(uri) {
+  gChromeMap.set(getBaseUriForChromeUri(uri), uri);
+}
+
+// formautofill registers resource://formautofill/ and
+// chrome://formautofill/content/ dynamically at runtime.
+// Bug 1480276 is about addressing this without this hard-coding.
+trackResourcePrefix("formautofill");
+trackChromeUri("chrome://formautofill/content/");
+
 function parseManifest(manifestUri) {
   return fetchFile(manifestUri.spec).then(data => {
     for (let line of data.split("\n")) {
       let [type, ...argv] = line.split(/\s+/);
       if (type == "content" || type == "skin" || type == "locale") {
         let chromeUri = `chrome://${argv[0]}/${type}/`;
-        gChromeMap.set(getBaseUriForChromeUri(chromeUri), chromeUri);
+        trackChromeUri(chromeUri);
       } else if (type == "override" || type == "overlay") {
         // Overlays aren't really overrides, but behave the same in
         // that the overlay is only referenced if the original xul
         // file is referenced somewhere.
         let os = "os=" + Services.appinfo.OS;
         if (!argv.some(s => s.startsWith("os=") && s != os)) {
           gOverrideMap.set(Services.io.newURI(argv[1]).specIgnoringRef,
                            Services.io.newURI(argv[0]).specIgnoringRef);
@@ -266,16 +276,45 @@ function parseManifest(manifestUri) {
         trackResourcePrefix(argv[0]);
       } else if (type == "component") {
         gComponentsSet.add(argv[1]);
       }
     }
   });
 }
 
+// If the given URI is a webextension manifest, extract the scripts
+// for any embedded APIs.  Returns the passed in URI if the manifest
+// is not a webextension manifest, null otherwise.
+async function parseJsonManifest(uri) {
+  let raw = await fetchFile(uri.spec);
+  let data;
+  try {
+    data = JSON.parse(raw);
+  } catch (ex) {
+    return uri;
+  }
+
+  // Simplistic test for whether this is a webextension manifest:
+  if (data.manifest_version !== 2) {
+    return uri;
+  }
+
+  if (data.experiment_apis) {
+    for (let api of Object.values(data.experiment_apis)) {
+      if (api.parent && api.parent.script) {
+        let script = uri.resolve(api.parent.script);
+        gReferencesFromCode.set(script, null);
+      }
+    }
+  }
+
+  return null;
+}
+
 function addCodeReference(url, fromURI) {
   let from = convertToCodeURI(fromURI.spec);
 
   // Ignore self references.
   if (url == from)
     return;
 
   let ref;
@@ -541,29 +580,42 @@ add_task(async function checkAllTheFiles
   // test infrastructure because it runs against jarfiles there, and
   // our zipreader APIs are all sync)
   let uris = await generateURIsFromDirTree(appDir, [".css", ".manifest", ".jpg", ".png", ".gif", ".svg",  ".dtd", ".properties"].concat(kCodeExtensions));
 
   // Parse and remove all manifests from the list.
   // NOTE that this must be done before filtering out devtools paths
   // so that all chrome paths can be recorded.
   let manifestURIs = [];
+  let jsonManifests = [];
   uris = uris.filter(uri => {
     let path = uri.pathQueryRef;
     if (path.endsWith(".manifest")) {
       manifestURIs.push(uri);
       return false;
+    } else if (path.endsWith("/manifest.json")) {
+      jsonManifests.push(uri);
+      return false;
     }
 
     return true;
   });
 
   // Wait for all manifest to be parsed
   await throttledMapPromises(manifestURIs, parseManifest);
 
+  // manifest.json is a common name, it is used for WebExtension manifests
+  // but also for other things.  To tell them apart, we have to actually
+  // read the contents.  This will populate gExtensionRoots with all
+  // embedded extension APIs, and return any manifest.json files that aren't
+  // webextensions.
+  let nonWebextManifests = (await Promise.all(jsonManifests.map(parseJsonManifest)))
+                                         .filter(uri => !!uri);
+  uris.push(...nonWebextManifests);
+
   addActorModules();
 
   // We build a list of promises that get resolved when their respective
   // files have loaded and produced no errors.
   let allPromises = [];
 
   for (let uri of uris) {
     let path = uri.pathQueryRef;