Add tabcloser files
authorGavin Sharp <gavin@mozilla.com>
Thu, 20 Nov 2008 12:02:14 -0500
changeset 0 4d0aefb59445
child 1 07ba23598de5
push id1
push usergsharp@mozilla.com
push dateThu, 20 Nov 2008 17:02:26 +0000
Add tabcloser files
build.sh
chrome.manifest
config_build.sh
content/firefoxOverlay.xul
content/overlay.js
defaults/preferences/tabcloser.js
install.rdf
locale/en-US/tabcloser.properties
readme.txt
skin/overlay.css
new file mode 100644
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,128 @@
+#!/bin/bash
+# build.sh -- builds JAR and XPI files for mozilla extensions
+#   by Nickolay Ponomarev <asqueella@gmail.com>
+#   (original version based on Nathan Yergler's build script)
+# Most recent version is at <http://kb.mozillazine.org/Bash_build_script>
+
+# This script assumes the following directory structure:
+# ./
+#   chrome.manifest (optional - for newer extensions)
+#   install.rdf
+#   (other files listed in $ROOT_FILES)
+#
+#   content/    |
+#   locale/     |} these can be named arbitrary and listed in $CHROME_PROVIDERS
+#   skin/       |
+#
+#   defaults/   |
+#   components/ |} these must be listed in $ROOT_DIRS in order to be packaged
+#   ...         |
+#
+# It uses a temporary directory ./build when building; don't use that!
+# Script's output is:
+# ./$APP_NAME.xpi
+# ./$APP_NAME.jar  (only if $KEEP_JAR=1)
+# ./files -- the list of packaged files
+#
+# Note: It modifies chrome.manifest when packaging so that it points to 
+#       chrome/$APP_NAME.jar!/*
+
+#
+# default configuration file is ./config_build.sh, unless another file is 
+# specified in command-line. Available config variables:
+APP_NAME=          # short-name, jar and xpi files name. Must be lowercase with no spaces
+CHROME_PROVIDERS=  # which chrome providers we have (space-separated list)
+CLEAN_UP=          # delete the jar / "files" when done?       (1/0)
+ROOT_FILES=        # put these files in root of xpi (space separated list of leaf filenames)
+ROOT_DIRS=         # ...and these directories       (space separated list)
+BEFORE_BUILD=      # run this before building       (bash command)
+AFTER_BUILD=       # ...and this after the build    (bash command)
+
+if [ -z $1 ]; then
+  . ./config_build.sh
+else
+  . $1
+fi
+
+if [ -z $APP_NAME ]; then
+  echo "You need to create build config file first!"
+  echo "Read comments at the beginning of this script for more info."
+  exit;
+fi
+
+ROOT_DIR=`pwd`
+TMP_DIR=build
+
+#uncomment to debug
+#set -x
+
+# remove any left-over files from previous build
+rm -f $APP_NAME.jar $APP_NAME.xpi files
+rm -rf $TMP_DIR
+
+$BEFORE_BUILD
+
+mkdir --parents --verbose $TMP_DIR/chrome
+
+# generate the JAR file, excluding CVS and temporary files
+JAR_FILE=$TMP_DIR/chrome/$APP_NAME.jar
+echo "Generating $JAR_FILE..."
+for CHROME_SUBDIR in $CHROME_PROVIDERS; do
+  find $CHROME_SUBDIR -path '*CVS*' -prune -o -type f -print | grep -v \~ >> files
+done
+
+zip -0 -r $JAR_FILE `cat files`
+# The following statement should be used instead if you don't wish to use the JAR file
+#cp --verbose --parents `cat files` $TMP_DIR/chrome
+
+# prepare components and defaults
+echo "Copying various files to $TMP_DIR folder..."
+for DIR in $ROOT_DIRS; do
+  mkdir $TMP_DIR/$DIR
+  FILES="`find $DIR -path '*CVS*' -prune -o -type f -print | grep -v \~`"
+  echo $FILES >> files
+  cp --verbose --parents $FILES $TMP_DIR
+done
+
+# Copy other files to the root of future XPI.
+for ROOT_FILE in $ROOT_FILES install.rdf chrome.manifest; do
+  cp --verbose $ROOT_FILE $TMP_DIR
+  if [ -f $ROOT_FILE ]; then
+    echo $ROOT_FILE >> files
+  fi
+done
+
+cd $TMP_DIR
+
+if [ -f "chrome.manifest" ]; then
+  echo "Preprocessing chrome.manifest..."
+  # You think this is scary?
+  #s/^(content\s+\S*\s+)(\S*\/)$/\1jar:chrome\/$APP_NAME\.jar!\/\2/
+  #s/^(skin|locale)(\s+\S*\s+\S*\s+)(.*\/)$/\1\2jar:chrome\/$APP_NAME\.jar!\/\3/
+  #
+  # Then try this! (Same, but with characters escaped for bash :)
+  sed -i -r s/^\(content\\s+\\S*\\s+\)\(\\S*\\/\)$/\\1jar:chrome\\/$APP_NAME\\.jar!\\/\\2/ chrome.manifest
+  sed -i -r s/^\(skin\|locale\)\(\\s+\\S*\\s+\\S*\\s+\)\(.*\\/\)$/\\1\\2jar:chrome\\/$APP_NAME\\.jar!\\/\\3/ chrome.manifest
+
+  # (it simply adds jar:chrome/whatever.jar!/ at appropriate positions of chrome.manifest)
+fi
+
+# generate the XPI file
+echo "Generating $APP_NAME.xpi..."
+zip -r ../$APP_NAME.xpi *
+
+cd "$ROOT_DIR"
+
+echo "Cleanup..."
+if [ $CLEAN_UP = 0 ]; then
+  # save the jar file
+  mv $TMP_DIR/chrome/$APP_NAME.jar .
+else
+  rm ./files
+fi
+
+# remove the working files
+rm -rf $TMP_DIR
+echo "Done!"
+
+$AFTER_BUILD
new file mode 100644
--- /dev/null
+++ b/chrome.manifest
@@ -0,0 +1,4 @@
+content	tabcloser	content/
+locale	tabcloser	en-US	locale/en-US/
+skin	tabcloser	classic/1.0	skin/
+overlay	chrome://browser/content/browser.xul	chrome://tabcloser/content/firefoxOverlay.xul
new file mode 100644
--- /dev/null
+++ b/config_build.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+# Build config for build.sh
+APP_NAME=tabcloser
+CHROME_PROVIDERS="content locale skin"
+CLEAN_UP=1
+ROOT_FILES=
+ROOT_DIRS="defaults"
+BEFORE_BUILD=
+AFTER_BUILD=
new file mode 100644
--- /dev/null
+++ b/content/firefoxOverlay.xul
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ***** BEGIN LICENSE BLOCK *****
+  -   Version: MPL 1.1/GPL 2.0/LGPL 2.1
+  -
+  - The contents of this file are subject to the Mozilla Public License Version
+  - 1.1 (the "License"); you may not use this file except in compliance with
+  - the License. You may obtain a copy of the License at
+  - http://www.mozilla.org/MPL/
+  - 
+  - Software distributed under the License is distributed on an "AS IS" basis,
+  - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  - for the specific language governing rights and limitations under the
+  - License.
+  -
+  - The Original Code is TabCloser.
+  -
+  - The Initial Developer of the Original Code is
+  - Gavin Sharp <gavin@gavinsharp.com>.
+  - Portions created by the Initial Developer are Copyright (C) 2008
+  - the Initial Developer. All Rights Reserved.
+  -
+  - Contributor(s):
+  -
+  - Alternatively, the contents of this file may be used under the terms of
+  - either the GNU General Public License Version 2 or later (the "GPL"), or
+  - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  - in which case the provisions of the GPL or the LGPL are applicable instead
+  - of those above. If you wish to allow use of your version of this file only
+  - under the terms of either the GPL or the LGPL, and not to allow others to
+  - use your version of this file under the terms of the MPL, indicate your
+  - decision by deleting the provisions above and replace them with the notice
+  - and other provisions required by the GPL or the LGPL. If you do not delete
+  - the provisions above, a recipient may use your version of this file under
+  - the terms of any one of the MPL, the GPL or the LGPL.
+  - 
+  - ***** END LICENSE BLOCK ***** -->
+
+<?xml-stylesheet href="chrome://tabcloser/skin/overlay.css" type="text/css"?>
+<overlay id="tabcloser-overlay"
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script src="overlay.js"/>
+  <stringbundleset id="stringbundleset">
+    <stringbundle id="tabcloser-strings" src="chrome://tabcloser/locale/tabcloser.properties"/>
+  </stringbundleset>
+</overlay>
new file mode 100644
--- /dev/null
+++ b/content/overlay.js
@@ -0,0 +1,103 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ *   Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is TabCloser.
+ *
+ * The Initial Developer of the Original Code is
+ * Gavin Sharp <gavin@gavinsharp.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ * 
+ * ***** END LICENSE BLOCK ***** */
+
+var tabcloser = {
+  onLoad: function() {
+    // initialization code
+    this.initialized = true;
+    this.strings = document.getElementById("tabcloser-strings");
+
+    this.tabMenu = document.getAnonymousElementByAttribute(getBrowser(), "anonid", "tabContextMenu");
+    var self = this;
+    this.tabMenu.addEventListener("popupshowing", function() { self.onMenuShowing(); }, false);
+
+    // Add the menu item
+    var closeTabMenuitem = this.tabMenu.getElementsByAttribute("id",
+                                                          "context_closeTab")[0];
+    var newButton = document.createElement("menuitem");
+    newButton.setAttribute("accesskey",
+                           this.strings.getString("closeTabsForSite.accesskey"));
+    newButton.setAttribute("oncommand", "tabcloser.onMenuItemCommand(event);");
+    this.contextMenuItem = this.tabMenu.insertBefore(newButton, closeTabMenuitem);
+  },
+
+  onMenuShowing: function (e) {
+    try {
+      // Might throw if current tab has no host...
+      var host = gBrowser.mContextTab.linkedBrowser.currentURI.host;
+    } catch (ex) {
+      // ... so just hide the menu item
+      this.contextMenuItem.hidden = true;
+      return;
+    }
+
+    this.contextMenuItem.hidden = false;
+    var label = this.strings.getFormattedString("closeTabsForSite.label",
+                                                [host]);
+    this.contextMenuItem.setAttribute("label", label);
+  },
+
+  onMenuItemCommand: function(e) {
+    var host = gBrowser.mContextTab.linkedBrowser.currentURI.host;
+
+    // prompt?
+    var message = this.strings.getFormattedString("areYouSure.message",
+                                                [host]);
+    var title = this.strings.getString("areYouSure");
+    var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
+                        getService(Ci.nsIPromptService);
+    var confirmed = promptService.confirm(null, title, message);
+    if (!confirmed)
+      return;
+
+    var tabCount = gBrowser.mTabs.length;
+    for (var i = tabCount - 1; i >= 0; i--) {
+      var tab = gBrowser.mTabs[i];
+      var browser = gBrowser.getBrowserForTab(tab);
+      try {
+        var tabHost = browser.currentURI.host;
+      } catch (ex) {
+        // Ignore failure to get .host
+        continue;
+      }
+      if (host == tabHost) {
+        gBrowser.removeTab(tab);
+      }
+    }
+  },
+
+};
+window.addEventListener("load", function(e) { tabcloser.onLoad(e); }, false);
new file mode 100644
--- /dev/null
+++ b/defaults/preferences/tabcloser.js
@@ -0,0 +1,2 @@
+// See http://kb.mozillazine.org/Localize_extension_descriptions
+pref("extensions.tabcloser@gavinsharp.com.description", "chrome://tabcloser/locale/tabcloser.properties");
new file mode 100644
--- /dev/null
+++ b/install.rdf
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
+ xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+  <Description about="urn:mozilla:install-manifest">
+    <em:id>tabcloser@gavinsharp.com</em:id>
+    <em:name>TabCloser</em:name>
+    <em:version>1.0</em:version>
+    <em:creator>Gavin Sharp</em:creator>
+    <em:description>Close all tabs for a given site.</em:description>
+    <em:targetApplication>
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- firefox -->
+        <em:minVersion>3.0</em:minVersion>
+        <em:maxVersion>3.1b2pre</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+  </Description>
+</RDF>
new file mode 100644
--- /dev/null
+++ b/locale/en-US/tabcloser.properties
@@ -0,0 +1,5 @@
+closeTabsForSite.label=Close all %S tabs
+closeTabsForSite.accesskey=l
+areYouSure=Are you sure?
+areYouSure.message=Are you sure you want to close all %S tabs?
+extensions.tabcloser.description=Close all tabs for a given site.
new file mode 100644
--- /dev/null
+++ b/readme.txt
@@ -0,0 +1,21 @@
+This extension was generated by the Extension Wizard at
+http://ted.mielczarek.org/code/mozilla/extensionwiz/ .
+This extension is compatible only with Firefox 1.5 and
+above.  Most of the files in this package are based on
+the 'helloworld' extension from the Mozillazine Knowledge Base.
+
+You can build an XPI for installation by running the
+build.sh script located in this folder.  For development
+you should do the following:
+  1. Unzip the entire contents of this package to somewhere,
+	       e.g, c:\dev or /home/user/dev
+  2. Put the full path to the folder (e.g. c:\dev\tabcloser on
+     Windows, /home/user/dev/tabcloser on Linux) in a file named
+     tabcloser@gavinsharp.com and copy that file to
+     [your profile folder]\extensions\
+  3. Restart Firefox.
+
+For more information, see the Mozillazine Knowledge Base:
+http://kb.mozillazine.org/Getting_started_with_extension_development
+
+-Ted Mielczarek <ted.mielczarek@gmail.com>
new file mode 100644
--- /dev/null
+++ b/skin/overlay.css
@@ -0,0 +1,5 @@
+/* This is just an example.  You shouldn't do this. */
+#tabcloser-hello
+{
+  color: red ! important;
+}