[Pkg-mozext-commits] [adblock-plus] 205/464: Generate bootstrap.js automatically if missing, also add standard modules to the package if necessary

David Prévot taffit at moszumanska.debian.org
Tue Jul 22 20:44:17 UTC 2014


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository adblock-plus.

commit 543aa6981da74b482f8444888c232f90bb9bc5db
Author: Wladimir Palant <trev at adblockplus.org>
Date:   Sat Jan 21 21:59:41 2012 +0100

    Generate bootstrap.js automatically if missing, also add standard modules to the package if necessary
---
 bootstrap.js.tmpl | 118 +++++++++++++++++++++++++++++++++++
 keySelector.js    | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 packager.py       |  53 +++++++++++++++-
 prefs.js          | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++
 windowObserver.js |  58 +++++++++++++++++
 5 files changed, 580 insertions(+), 1 deletion(-)

diff --git a/bootstrap.js.tmpl b/bootstrap.js.tmpl
new file mode 100644
index 0000000..3d90603
--- /dev/null
+++ b/bootstrap.js.tmpl
@@ -0,0 +1,118 @@
+/*
+ * This Source Code is subject to the terms of the Mozilla Public License
+ * version 2.0 (the "License"). You can obtain a copy of the License at
+ * http://mozilla.org/MPL/2.0/.
+ */
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+let addonData = null;
+
+function install(params, reason) {}
+function uninstall(params, reason) {}
+
+function startup(params, reason)
+{
+  {%- if hasChrome %}
+  if (Services.vc.compare(Services.appinfo.platformVersion, "10.0") < 0)
+    Components.manager.addBootstrappedManifestLocation(params.installPath);
+  {%- endif %}
+
+  addonData = params;
+  {%- if hasChromeRequires %}
+  Services.obs.addObserver(RequireObserver, "{{metadata.get('general', 'basename')}}-require", true);
+  {%- endif %}
+
+  require("appIntegration").AppIntegration.init();
+}
+
+function shutdown(params, reason)
+{
+  require("appIntegration").AppIntegration.shutdown();
+
+  {%- if chromeWindows %}
+  let windowNames = {{chromeWindows|json}};
+  for (let i = 0; i < windowNames.length; i++)
+  {
+    let enumerator = Services.wm.getEnumerator(windowNames[i]);
+    while (enumerator.hasMoreElements())
+    {
+      let window = enumerator.getNext().QueryInterface(Ci.nsIDOMWindow);
+      window.setTimeout("window.close()", 0); // Closing immediately might not work due to modal windows
+      try
+      {
+        window.close();
+      } catch(e) {}
+    }
+  }
+  {%- endif %}
+
+  {%- if hasChromeRequires %}
+  Services.obs.removeObserver(RequireObserver, "{{metadata.get('general', 'basename')}}-require");
+  {%- endif %}
+  addonData = null;
+  require.scopes = {__proto__: null};
+
+  {%- if hasChrome %}
+  if (Services.vc.compare(Services.appinfo.platformVersion, "10.0") < 0)
+    Components.manager.removeBootstrappedManifestLocation(params.installPath);
+  {%- endif %}
+}
+
+function require(module)
+{
+  let scopes = require.scopes;
+  if (!(module in scopes))
+  {
+    {%- if 'info' in requires %}
+    if (module == "info")
+    {
+      scopes[module] = {};
+      scopes[module].exports =
+      {
+        addonID: addonData.id,
+        addonVersion: addonData.version,
+        addonRoot: addonData.resourceURI.spec,
+      };
+    }
+    else
+    {
+    {%- endif %}
+      scopes[module] = {require: require, {% if hasUnrequires %}unrequire: unrequire, {% endif %}exports: {}};
+      Services.scriptloader.loadSubScript(addonData.resourceURI.spec + module + ".js", scopes[module]);
+    {%- if 'info' in requires %}
+    }
+    {%- endif %}
+  }
+  return scopes[module].exports;
+}
+require.scopes = {__proto__: null};
+
+{%- if hasUnrequires %}
+function unrequire(module)
+{
+  delete require.scopes[module];
+}
+{%- endif %}
+
+{%- if hasChromeRequires %}
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+let RequireObserver =
+{
+  observe: function(subject, topic, data)
+  {
+    if (topic == "{{metadata.get('general', 'basename')}}-require")
+    {
+      subject.wrappedJSObject.exports = require(data);
+    }
+  },
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIObserver])
+};
+{%- endif %}
diff --git a/keySelector.js b/keySelector.js
new file mode 100644
index 0000000..3d57cb8
--- /dev/null
+++ b/keySelector.js
@@ -0,0 +1,182 @@
+/*
+ * This Source Code is subject to the terms of the Mozilla Public License
+ * version 2.0 (the "License"). You can obtain a copy of the License at
+ * http://mozilla.org/MPL/2.0/.
+ */
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
+/**
+ * Translation table for key modifier names.
+ */
+let validModifiers =
+{
+  ACCEL: "control",
+  CTRL: "control",
+  CONTROL: "control",
+  SHIFT: "shift",
+  ALT: "alt",
+  META: "meta",
+  __proto__: null
+};
+
+let existingShortcuts = null;
+
+/**
+ * Sets the correct value of validModifiers.ACCEL.
+ */
+function initAccelKey()
+{
+  try
+  {
+    let accelKey = Services.prefs.getIntPref("ui.key.accelKey");
+    if (accelKey == Ci.nsIDOMKeyEvent.DOM_VK_CONTROL)
+      validModifiers.ACCEL = "control";
+    else if (accelKey == Ci.nsIDOMKeyEvent.DOM_VK_ALT)
+      validModifiers.ACCEL = "alt";
+    else if (accelKey == Ci.nsIDOMKeyEvent.DOM_VK_META)
+      validModifiers.ACCEL = "meta";
+  }
+  catch(e)
+  {
+    Cu.reportError(e);
+  }
+}
+
+/**
+ * Finds out which keyboard shortcuts are already taken in an application window,
+ * converts them to canonical form in the existingShortcuts variable.
+ */
+function initExistingShortcuts(/**ChromeWindow*/ window)
+{
+  existingShortcuts = {__proto__: null};
+
+  let keys = window.document.getElementsByTagName("key");
+  for (let i = 0; i < keys.length; i++)
+  {
+    let key = keys[i];
+    let keyData =
+    {
+      shift: false,
+      meta: false,
+      alt: false,
+      control: false,
+      char: null,
+      code: null
+    };
+
+    let keyChar = key.getAttribute("key");
+    if (keyChar && keyChar.length == 1)
+      keyData.char = keyChar.toUpperCase();
+
+    let keyCode = key.getAttribute("keycode");
+    if (keyCode && "DOM_" + keyCode.toUpperCase() in Ci.nsIDOMKeyEvent)
+      keyData.code = Ci.nsIDOMKeyEvent["DOM_" + keyCode.toUpperCase()];
+
+    if (!keyData.char && !keyData.code)
+      continue;
+
+    let keyModifiers = key.getAttribute("modifiers");
+    if (keyModifiers)
+      for each (let modifier in keyModifiers.toUpperCase().match(/\w+/g))
+        if (modifier in validModifiers)
+          keyData[validModifiers[modifier]] = true;
+
+    let canonical = [keyData.shift, keyData.meta, keyData.alt, keyData.control, keyData.char || keyData.code].join(" ");
+    existingShortcuts[canonical] = true;
+  }
+}
+
+/**
+ * Creates the text representation for a key.
+ */
+function getTextForKey(/**Object*/ keyData) /**String*/
+{
+  try
+  {
+    let stringBundle = Services.strings.createBundle("chrome://global-platform/locale/platformKeys.properties");
+    let parts = [];
+    if (keyData.control)
+      parts.push(stringBundle.GetStringFromName("VK_CONTROL"));
+    if (keyData.alt)
+      parts.push(stringBundle.GetStringFromName("VK_ALT"));
+    if (keyData.meta)
+      parts.push(stringBundle.GetStringFromName("VK_META"));
+    if (keyData.shift)
+      parts.push(stringBundle.GetStringFromName("VK_SHIFT"));
+    if (keyData.char)
+      parts.push(keyData.char.toUpperCase());
+    else
+    {
+      let stringBundle2 = Services.strings.createBundle("chrome://global/locale/keys.properties");
+      parts.push(stringBundle2.GetStringFromName(keyData.codeName));
+    }
+    return parts.join(stringBundle.GetStringFromName("MODIFIER_SEPARATOR"));
+  }
+  catch (e)
+  {
+    Cu.reportError(e);
+    return null;
+  }
+}
+
+exports.selectKey = selectKey;
+
+/**
+ * Selects a keyboard shortcut variant that isn't already taken in the window,
+ * parses it into an object.
+ */
+function selectKey(/**ChromeWindow*/ window, /**String*/ variants) /**Object*/
+{
+  if (!existingShortcuts)
+  {
+    initAccelKey();
+    initExistingShortcuts(window);
+  }
+
+  for each (let variant in variants.split(/\s*,\s*/))
+  {
+    if (!variant)
+      continue;
+
+    let keyData =
+    {
+      shift: false,
+      meta: false,
+      alt: false,
+      control: false,
+      char: null,
+      code: null,
+      codeName: null,
+      text: null
+    };
+    for each (let part in variant.toUpperCase().split(/\s+/))
+    {
+      if (part in validModifiers)
+        keyData[validModifiers[part]] = true;
+      else if (part.length == 1)
+        keyData.char = part;
+      else if ("DOM_VK_" + part in Ci.nsIDOMKeyEvent)
+      {
+        keyData.code = Ci.nsIDOMKeyEvent["DOM_VK_" + part];
+        keyData.codeName = "VK_" + part;
+      }
+    }
+
+    if (!keyData.char && !keyData.code)
+      continue;
+
+    let canonical = [keyData.shift, keyData.meta, keyData.alt, keyData.control, keyData.char || keyData.code].join(" ");
+    if (canonical in existingShortcuts)
+      continue;
+
+    keyData.text = getTextForKey(keyData);
+    return keyData;
+  }
+
+  return null;
+}
diff --git a/packager.py b/packager.py
index b8a48a5..45b0271 100644
--- a/packager.py
+++ b/packager.py
@@ -4,7 +4,7 @@
 # version 2.0 (the "License"). You can obtain a copy of the License at
 # http://mozilla.org/MPL/2.0/.
 
-import os, sys, re, subprocess, jinja2, buildtools, codecs, hashlib, base64, shutil, urllib
+import os, sys, re, subprocess, jinja2, buildtools, codecs, hashlib, base64, shutil, urllib, json
 from ConfigParser import SafeConfigParser
 from StringIO import StringIO
 from zipfile import ZipFile, ZIP_STORED, ZIP_DEFLATED
@@ -217,6 +217,55 @@ def readXPIFiles(baseDir, params, files):
     if os.path.exists(path):
       readFile(files, params, path, os.path.basename(path))
 
+def addMissingFiles(baseDir, params, files):
+  hasChrome = False
+  hasChromeRequires = False
+  hasUnrequires = False
+  chromeWindows = []
+  requires = {}
+  for name, content in files.iteritems():
+    if name == 'chrome.manifest':
+      hasChrome = True
+    if name.startswith('chrome/content/') and name.endswith('.js') and re.search(r'\srequire\(', content):
+      hasChromeRequires = True
+    if not '/' in name and name.endswith('.js') and re.search(r'\sunrequire\(', content):
+      hasUnrequires = True
+    if name.endswith('.js'):
+      for match in re.finditer(r'\srequire\("(\w+)"\)', content):
+        requires[match.group(1)] = True
+    if name.endswith('.xul'):
+      match = re.search(r'<(?:window|dialog)\s[^>]*\bwindowtype="([^">]+)"', content)
+      if match:
+        chromeWindows.append(match.group(1))
+
+  while True:
+    missing = []
+    for module in requires:
+      moduleFile = module + '.js'
+      if not moduleFile in files:
+        path = os.path.join(buildtools.__path__[0], moduleFile)
+        if os.path.exists(path):
+          missing.append((path, moduleFile))
+    if not len(missing):
+      break
+    for path, moduleFile in missing:
+      readFile(files, params, path, moduleFile)
+      for match in re.finditer(r'\srequire\("(\w+)"\)', files[moduleFile]):
+        requires[match.group(1)] = True
+
+  env = jinja2.Environment(loader=jinja2.FileSystemLoader(buildtools.__path__[0]))
+  env.filters['json'] = json.dumps
+  template = env.get_template('bootstrap.js.tmpl')
+  templateData = {
+    'hasChrome': hasChrome,
+    'hasChromeRequires': hasChromeRequires,
+    'hasUnrequires': hasUnrequires,
+    'chromeWindows': chromeWindows,
+    'requires': requires,
+    'metadata': params['metadata'],
+  }
+  files['bootstrap.js'] = processFile('bootstrap.js', template.render(templateData).encode('utf-8'), params)
+
 def signFiles(files, keyFile):
   import M2Crypto
   manifest = []
@@ -315,6 +364,8 @@ def createBuild(baseDir, outFile=None, locales=None, buildNum=None, releaseBuild
   else:
     files['chrome/%s.jar' % metadata.get('general', 'baseName')] = createChromeJar(baseDir, params)
   readXPIFiles(baseDir, params, files)
+  if metadata.has_option('general', 'restartless') and not 'bootstrap.js' in files:
+    addMissingFiles(baseDir, params, files)
   if keyFile:
     signFiles(files, keyFile)
   writeXPI(files, outFile)
diff --git a/prefs.js b/prefs.js
new file mode 100644
index 0000000..06761b9
--- /dev/null
+++ b/prefs.js
@@ -0,0 +1,170 @@
+/*
+ * This Source Code is subject to the terms of the Mozilla Public License
+ * version 2.0 (the "License"). You can obtain a copy of the License at
+ * http://mozilla.org/MPL/2.0/.
+ */
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+let {addonRoot} = require("info");
+
+let Prefs = exports.Prefs =
+{
+  branch: null,
+  ignorePrefChanges: false,
+
+  init: function(branchName, migrate)
+  {
+    if (this.branch)
+      return;
+    this.branch = Services.prefs.getBranch(branchName);
+
+    /**
+     * Sets up getter/setter on Prefs object for preference.
+     */
+    function defineProperty(/**String*/ name, defaultValue, /**Function*/ readFunc, /**Function*/ writeFunc)
+    {
+      let value = defaultValue;
+      this["_update_" + name] = function()
+      {
+        try
+        {
+          value = readFunc(this.branch, name);
+        }
+        catch(e)
+        {
+          Cu.reportError(e);
+        }
+      };
+      Prefs.__defineGetter__(name, function() value);
+      Prefs.__defineSetter__(name, function(newValue)
+      {
+        if (value == newValue)
+          return value;
+
+        try
+        {
+          this.ignorePrefChanges = true;
+          writeFunc(this.branch, name, newValue);
+          value = newValue;
+        }
+        catch(e)
+        {
+          Cu.reportError(e);
+        }
+        finally
+        {
+          this.ignorePrefChanges = false;
+        }
+        return value;
+      });
+      this["_update_" + name]();
+    }
+
+    // Load default preferences and set up properties for them
+    let defaultBranch = Services.prefs.getDefaultBranch(branchName);
+    let typeMap =
+    {
+      boolean: [getBoolPref, setBoolPref],
+      number: [getIntPref, setIntPref],
+      string: [getCharPref, setCharPref],
+      object: [getJSONPref, setJSONPref]
+    };
+    let scope =
+    {
+      pref: function(pref, value)
+      {
+        if (pref.substr(0, branchName.length) != branchName)
+        {
+          Cu.reportError(new Error("Ignoring default preference " + pref + ", wrong branch."));
+          return;
+        }
+        pref = pref.substr(branchName.length);
+
+        let [getter, setter] = typeMap[typeof value];
+        setter(defaultBranch, pref, value);
+        defineProperty.call(Prefs, pref, false, getter, setter);
+      }
+    };
+    Services.scriptloader.loadSubScript(addonRoot + "defaults/preferences/prefs.js", scope);
+
+    // Add preference change observer
+    try
+    {
+      this.branch.QueryInterface(Ci.nsIPrefBranch2)
+                 .addObserver("", this, true);
+    }
+    catch (e)
+    {
+      Cu.reportError(e);
+    }
+
+    // Migrate preferences stored under outdated names
+    if (migrate)
+    {
+      for (let oldName in migrate)
+      {
+        let newName = migrate[oldName];
+        if (newName in this && Services.prefs.prefHasUserValue(oldName))
+        {
+          let [getter, setter] = typeMap[typeof this[newName]];
+          try
+          {
+            this[newName] = getter(Services.prefs, oldName);
+          } catch(e) {}
+          Services.prefs.clearUserPref(oldName);
+        }
+      }
+    }
+  },
+
+  shutdown: function()
+  {
+    if (!this.branch)
+      return;
+
+    try
+    {
+      this.branch.QueryInterface(Ci.nsIPrefBranch2)
+                 .removeObserver("", this);
+    }
+    catch (e)
+    {
+      Cu.reportError(e);
+    }
+    this.branch = null;
+  },
+
+  observe: function(subject, topic, data)
+  {
+    if (this.ignorePrefChanges || topic != "nsPref:changed")
+      return;
+
+    if ("_update_" + data in this)
+      this["_update_" + data]();
+  },
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIObserver])
+};
+
+function getIntPref(branch, pref) branch.getIntPref(pref)
+function setIntPref(branch, pref, newValue) branch.setIntPref(pref, newValue)
+
+function getBoolPref(branch, pref) branch.getBoolPref(pref)
+function setBoolPref(branch, pref, newValue) branch.setBoolPref(pref, newValue)
+
+function getCharPref(branch, pref) branch.getComplexValue(pref, Ci.nsISupportsString).data
+function setCharPref(branch, pref, newValue)
+{
+  let str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
+  str.data = newValue;
+  branch.setComplexValue(pref, Ci.nsISupportsString, str);
+}
+
+function getJSONPref(branch, pref) JSON.parse(getCharPref(branch, pref))
+function setJSONPref(branch, pref, newValue) setCharPref(branch, pref, JSON.stringify(newValue))
diff --git a/windowObserver.js b/windowObserver.js
new file mode 100644
index 0000000..4bd23b0
--- /dev/null
+++ b/windowObserver.js
@@ -0,0 +1,58 @@
+/*
+ * This Source Code is subject to the terms of the Mozilla Public License
+ * version 2.0 (the "License"). You can obtain a copy of the License at
+ * http://mozilla.org/MPL/2.0/.
+ */
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+let WindowObserver = exports.WindowObserver =
+{
+  listener: null,
+
+  init: function(listener)
+  {
+    if (this.listener)
+      return;
+    this.listener = listener;
+
+    let e = Services.ww.getWindowEnumerator();
+    while (e.hasMoreElements())
+      this.listener.applyToWindow(e.getNext().QueryInterface(Ci.nsIDOMWindow));
+
+    Services.ww.registerNotification(this);
+  },
+
+  shutdown: function()
+  {
+    if (!this.listener)
+      return;
+
+    let e = Services.ww.getWindowEnumerator();
+    while (e.hasMoreElements())
+      this.listener.removeFromWindow(e.getNext().QueryInterface(Ci.nsIDOMWindow));
+
+    Services.ww.unregisterNotification(this);
+    this.listener = null;
+  },
+
+  observe: function(subject, topic, data)
+  {
+    if (topic == "domwindowopened")
+    {
+      let window = subject.QueryInterface(Ci.nsIDOMWindow);
+      window.addEventListener("DOMContentLoaded", function()
+      {
+        if (this.listener)
+          this.listener.applyToWindow(window);
+      }.bind(this), false);
+    }
+  },
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIObserver])
+};

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/adblock-plus.git



More information about the Pkg-mozext-commits mailing list