Refactor extension to webpack

This change is the biggest in the history of the project. The entire
project has been refactored so it is built with webpack.

This involves:
- Creating webpack and npm config files.
- Fixing some bugs in the code due to the fact that webpack uses strict
mode.
- Merging some pieces of code which were shared throughout the codebase
(not exhaustive, more work should be done in this direction).
- Splitting the console_inject.js file into separate files (it had 1000+
lines).
- Adapting all the build-related files (Makefile, bash scripts, etc.)
- Changing the docs to explain the new build process.
- Changing the Zuul playbook/roles to adapt to the new build process.

Change-Id: I16476d47825461c3a318b3f1a1eddb06b2df2e89
diff --git a/tools/generateManifest.go b/tools/generateManifest.go
new file mode 100644
index 0000000..185f1c3
--- /dev/null
+++ b/tools/generateManifest.go
@@ -0,0 +1,111 @@
+package main
+
+import (
+  "bufio"
+  "flag"
+  "fmt"
+  "io"
+  "log"
+  "os"
+  "regexp"
+  "strings"
+)
+
+// Generates the manifest.json file according to the dependencies passed
+// via CLI arguments
+
+const (
+  manifestTemplate = "templates/manifest.gjson"
+)
+
+var beginningOfIfStatement = regexp.MustCompile(`^\s*#if defined\(([^\(\)]*)\)\s*$`)
+var endOfIfStatement = regexp.MustCompile(`^\s*#endif\s*$`)
+
+var (
+  quietMode = flag.Bool("quiet", false, "Quiet mode")
+  destFile  = flag.String("dest", "", "Destination file")
+)
+
+func FindWithCaseFolding(slice []string, val string) bool {
+  for _, item := range slice {
+    if strings.EqualFold(item, val) {
+      return true
+    }
+  }
+  return false
+}
+
+func WriteManifest(template io.Reader, dest io.Writer, dependencies []string) error {
+  level := 0
+  activeLevel := 0
+  scanner := bufio.NewScanner(template)
+  for scanner.Scan() {
+    line := scanner.Text()
+    considerLine := false
+    if m := beginningOfIfStatement.FindStringSubmatch(line); m != nil {
+      if level == activeLevel {
+        statementDeps := m[1]
+        deps := strings.Split(statementDeps, "||")
+        for _, dep := range deps {
+          dep = strings.TrimSpace(dep)
+          if FindWithCaseFolding(dependencies, dep) {
+            activeLevel++
+            break
+          }
+        }
+      }
+      level++
+    } else if m := endOfIfStatement.MatchString(line); m {
+      if activeLevel == level {
+        activeLevel--
+      }
+      level--
+    } else {
+      considerLine = level == activeLevel
+    }
+
+    if considerLine {
+      _, err := io.WriteString(dest, line + "\n")
+      if err != nil {
+        return fmt.Errorf("Can't write manifest: %v", err)
+      }
+    }
+  }
+
+  return nil
+}
+
+func main() {
+  log.SetPrefix("generateManifest: ")
+  log.SetFlags(0)
+
+  flag.Parse()
+  dependencies := flag.Args()
+
+  if len(dependencies) == 0 {
+    log.Fatalf("Pass the dependencies as arguments (for instance, run `go run generateManifest.go CHROMIUM`).")
+  }
+
+  if *destFile == "" {
+    log.Fatalf("Pass the destination file name via the -dest flag.")
+  }
+
+  template, err := os.Open(manifestTemplate)
+  if err != nil {
+    log.Fatalf("Couldn't open file %v: %v", manifestTemplate, err)
+  }
+  defer template.Close()
+
+  dest, err := os.Create(*destFile)
+  if err != nil {
+    log.Fatalf("Couldn't create file %v: %v", *destFile, err)
+  }
+  defer dest.Close()
+
+  err = WriteManifest(template, dest, dependencies)
+  if err != nil {
+    log.Fatalf("%v", err)
+  } else if !*quietMode {
+    log.Println("Manifest has been generated successfully")
+  }
+}