Add Firefox support

The release.bash script has been updated, and now depends on a helper
script called generateManifest.bash. A "--browser" flag (shorthand "-b")
has been added to the script in order to specify the target browser.

Now the manifest.json file is saved as a template at
templates/manifest.gjson (gjson stands for Generic JSON), which includes
conditional clauses which indicate what parts of the manifest are
applicable to each browser.

generateManifest.bash generates the src/manifest.json file.

Change-Id: Ib051f3d893045c1377007b9b076ffa7a702d9648
diff --git a/.gitignore b/.gitignore
index ec335e0..ef9d424 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-console_inject_deprecated.js
 out
+src/manifest.json
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a2fb83e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,18 @@
+.PHONY: all chromium-stable chromium-beta gecko-stable gecko-beta clean
+
+all: chromium-stable chromium-beta gecko-stable gecko-beta
+
+chromium-stable:
+	bash release.bash -c stable -b chromium
+
+chromium-beta:
+	bash release.bash -c beta -b chromium
+
+gecko-stable:
+	bash release.bash -c stable -b gecko
+
+gecko-beta:
+	bash release.bash -c beta -b gecko
+
+clean:
+	rm -rf out
diff --git a/README.md b/README.md
index e0c2166..211b92f 100644
--- a/README.md
+++ b/README.md
@@ -7,26 +7,45 @@
 When the code in the `master` branch is considered to be stable, a release can be made. This is the procedure:
 
 1. Tag the last commit with a version number (in the format `vx`, where x is the extension's [version number](https://developer.chrome.com/extensions/manifest/version) for that release) by running `git tag -a vx -m "vx"`. Note that the tag should be an annotated tag and not a lightweight tag, and it must be pushed to Gerrit after being created.
-2. Build the extension for both the stable and beta channels (this is explained in the next section). This will output a ZIP file for each release channel.
-3. [Upload both release files](https://developer.chrome.com/webstore/publish#upload-your-item) to the Chrome Web Store, one for each release channel.
-4. [Submit both releases](https://developer.chrome.com/webstore/publish#submit-your-item-for-publishing) to be reviewed by the Chrome Web Store team, but in the case of the stable channel uncheck the "Publish automatically after it has passed review" option.
-5. Upload the beta release file to the [GitHub releases page](https://github.com/avm99963/infinitegforums/releases) under the newly created tag. Mark that release as a pre-release at GitHub.
-6. Wait until the beta release is reviewed and approved by Google.
-7. Test again the extension by using the beta channel. Check if the options have been transfered correctly from version to version, and wait some days (for instance between 3 and 5 days) to see if other people report issues with the updated version.
-8. If everything goes well, publish the update in the stable channel. The updated version should have already been reviewed by the Chrome Web Store team at this time.
-9. Update the release file in the GitHub releases page by removing the beta release file and uploading the stable release file. Also, remove the pre-release label.
+2. Build the extension for both the stable and beta channels (this is explained in the next section). This will output a ZIP file for each release channel and each supported browser.
+
+Afterwards, the release/build files must be submitted to the Chrome Web Store and addons.mozilla.org.
+
+### Submitting to the Chrome Web Store
+1. [Upload both release files](https://developer.chrome.com/webstore/publish#upload-your-item) to the Chrome Web Store, one for each release channel.
+2. [Submit both releases](https://developer.chrome.com/webstore/publish#submit-your-item-for-publishing) to be reviewed by the Chrome Web Store team, but in the case of the stable channel uncheck the "Publish automatically after it has passed review" option.
+3. Upload the beta release file to the [GitHub releases page](https://github.com/avm99963/infinitegforums/releases) under the newly created tag. Mark that release as a pre-release at GitHub.
+4. Wait until the beta release is reviewed and approved by Google.
+5. Test again the extension by using the beta channel. Check if the options have been transfered correctly from version to version, and wait some days (for instance between 3 and 5 days) to see if other people report issues with the updated version.
+6. If everything goes well, publish the update in the stable channel. The updated version should have already been reviewed by the Chrome Web Store team at this time.
+7. Update the release file in the GitHub releases page by removing the beta release file and uploading the stable release file. Also, remove the pre-release label.
 
 If during this process the release wasn't approved by Google or an issue was found during beta testing, a new release which fixes this should be created.
 
+### Submitting to addons.mozilla.org
+The procedure is similar to the one with the Chrome Web Store.
+
+@TODO: Add more details once the first version of the extension has been uploaded to addons.mozilla.org.
+
 ## Build the extension
-To create a zip file with the contents of the extension, which can be uploaded to the Chrome Web Store, run `bash release.bash`. You can also use `bash release.bash --channel=beta` to include a beta label in the extension name and version of the resulting zip file.
+A zip file with the contents of the extension, which can be uploaded to the Chrome Web Store and addons.mozilla.org, can be created with any of the following procedures:
 
-The ZIP file will contain a manifest.json file with the according version name, and will be located in the `out` folder.
+### Using the release.bash script
+Run `bash release.bash -h` in order to learn how to use this command. To summarize, the command accepts the `--channel` and `--browser` flags (or their short versions `-c` and `-b`).
 
-You can also get information about how to use the `release.bash` script by running `bash release.bash -h`.
+As an example, if you wanted to create a ZIP file of the beta-branded extension targeted for Firefox, you would run `bash release.bash -c beta -b gecko`.
+
+### Using make
+You can also use _make_ to build the extension. This is just a wrapper for the `release.bash` command.
+
+Run `make all` to build the extension for all the available channels and browsers. You can also run `make {target}` where `{target}` is one of the following: `chromium-stable`, `chromium-beta`, `gecko-stable`, `gecko-beta`.
+
+Run `make clean` to clean all the release files (this removes the `out` folder, which is where the release files are saved).
 
 ## Testing notes
+When testing the extension during development, you don't have to build the extension each time you want to import an updated version to Chrome/Firefox. Instead, run `bash generateManifest.bash {browser}` once, where `{browser}` is either `chromium` or `gecko`, and this will generate a `manifest.json` file for the specified browser in the `src` directory. Now, you can load the `src` folder directly in the browser in order to import the extension, which removes the need to build it. When the `manifest.gjson` file is modified, you'll have to generate the manifest again.
+
 To test translations, you might want to set your browser's locale. This section tells you how to set the locale in [Windows](https://developer.chrome.com/extensions/i18n#testing-win), [Mac OS X](https://developer.chrome.com/extensions/i18n#testing-mac), [Linux](https://developer.chrome.com/extensions/i18n#testing-linux), and [Chrome OS](https://developer.chrome.com/extensions/i18n#testing-chromeos).
 
 ## Beta channel
-The beta channel is available [here](https://chrome.google.com/webstore/detail/infinite-scroll-in-tw-bet/memmklnkkhifmflmidnflfcdepamljef).
+The beta channel for Chrome is available [here](https://chrome.google.com/webstore/detail/infinite-scroll-in-tw-bet/memmklnkkhifmflmidnflfcdepamljef).
diff --git a/generateManifest.bash b/generateManifest.bash
new file mode 100644
index 0000000..dd7df4e
--- /dev/null
+++ b/generateManifest.bash
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+# Generates the manifest.json file according to the dependencies passed
+# via CLI arguments
+
+dependencies=( "$@" )
+
+rm -f src/manifest.json
+cp templates/manifest.gjson src/manifest.json
+
+for dep in "${dependencies[@]}"; do
+  perl -0777 -pi -e "s/^#if defined\($dep\)\n([^#]*)#endif\n/\$1/gms" src/manifest.json
+done
+
+perl -0777 -pi -e "s/^#if defined\([^\n#]+\)\n[^#]*#endif\n//gms" src/manifest.json
diff --git a/release.bash b/release.bash
index 7c1aebe..311d6c6 100644
--- a/release.bash
+++ b/release.bash
@@ -8,7 +8,10 @@
 
   optional arguments:
     -h, --help     show this help message and exit
-    -c, --channel  indicates the channel of the release. Can be "beta" or "stable".
+    -c, --channel  indicates the channel of the release. Can be "beta"
+                   or "stable". Defaults to "stable".
+    -b, --browser  indicates the target browser for the release. Can be
+                   "chromium" or "gecko". Defaults to "chromium".
 
 END
 }
@@ -19,15 +22,17 @@
 }
 
 # Get options
-opts=$(getopt -l "help,channel:" -o "hc:" -n "$progname" -- "$@")
+opts=$(getopt -l "help,channel:,browser:" -o "hc:b:" -n "$progname" -- "$@")
 eval set -- "$opts"
 
 channel=stable
+browser=chromium
 
 while true; do
   case "$1" in
     -h | --help ) usage; exit; ;;
     -c | --channel ) channel="$2"; shift 2 ;;
+    -b | --browser ) browser="$2"; shift 2 ;;
     * ) break ;;
   esac
 done
@@ -38,8 +43,20 @@
   exit
 fi
 
+if [[ $browser != "chromium" && $browser != "gecko" ]]; then
+  echo "browser parameter value is incorrect."
+  usage
+  exit
+fi
+
 echo "Started building release..."
 
+# First of all, generate the appropriate manifest.json file for the
+# target browser
+dependencies=( ${browser^^} )
+
+bash generateManifest.bash "${dependencies[@]}"
+
 # This is the version name which git gives us
 version=$(git describe --always --tags --dirty)
 
@@ -59,18 +76,19 @@
 if [[ $channel == "beta" ]]; then
   # Change manifest.json to label the release as beta
   set_manifest_field "name" "__MSG_appNameBeta__"
+
+  if [[ $browser == "gecko" ]]; then
+    # Change the extension ID
+    set_manifest_field "id" "twpowertools+beta@avm99963.com"
+  fi
 fi
 
 # Create ZIP file for upload to the Chrome Web Store
 mkdir -p out
-rm -rf out/twpowertools-$version-$channel.zip
-zip -rq out/twpowertools-$version-$channel.zip src -x *.git*
+rm -rf out/twpowertools-$version-$browser-$channel.zip
+zip -rq out/twpowertools-$version-$browser-$channel.zip src -x *.git*
 
-# Revert manifest.json changes
-set_manifest_field "version" "0"
-set_manifest_field "version_name" "dirty"
-if [[ $channel == "beta" ]]; then
-  set_manifest_field "name" "__MSG_appName__"
-fi
+# Clean generated manifest.json file
+rm -f src/manifest.json
 
 echo "Done!"
diff --git a/src/manifest.json b/templates/manifest.gjson
similarity index 75%
rename from src/manifest.json
rename to templates/manifest.gjson
index 0b753d8..b8ce324 100644
--- a/src/manifest.json
+++ b/templates/manifest.gjson
@@ -2,7 +2,9 @@
   "manifest_version": 2,
   "name": "__MSG_appName__",
   "version": "0",
+#if defined(CHROMIUM)
   "version_name": "dirty",
+#endif
   "description": "__MSG_appDescription__",
   "icons": {
     "512": "icons/512.png",
@@ -38,15 +40,32 @@
     "https://support.google.com/*/thread/*",
     "storage"
   ],
+#if defined(CHROMIUM)
   "options_page": "options.html",
+#endif
   "options_ui": {
     "page": "options.html",
+#if defined(CHROMIUM)
     "chrome_style": true,
+#endif
+#if defined(GECKO)
+    "browser_style": true,
+#endif
     "open_in_tab": false
   },
   "background": {
-    "scripts": ["background.js"],
-    "persistent": false
+#if defined(CHROMIUM)
+    "persistent": false,
+#endif
+    "scripts": ["background.js"]
   },
+#if defined(GECKO)
+  "browser_specific_settings": {
+    "gecko": {
+      "id": "twpowertools@avm99963.com",
+      "strict_min_version": "55.0"
+    }
+  },
+#endif
   "default_locale": "en"
 }