includes/scriptdb.js
author Dave Townsend <dtownsend@oxymoronical.com>
Fri Jul 09 12:41:11 2010 -0700 (7 weeks ago)
changeset 0 f8b0b8c6f940
child 2 5fd42918d6f5
permissions -rw-r--r--
Initial import of demo extension
     1 const DB_SCHEMA = 1;

     2 const ID_SUFFIX = "@slipperymonkey.fractalbrew.com";

     3 

     4 var TAGMATCH = /^.*@(\S+)\s*(.*)/

     5 

     6 var ScriptDatabase = {

     7   db: null,

     8 

     9   startup: function() {

    10     var dbfile = Services.dirsvc.get("ProfD", Ci.nsIFile);

    11     dbfile.append("slippery.sqlite");

    12     this.db = Services.storage.openUnsharedDatabase(dbfile);

    13     if (this.db.schemaVersion < DB_SCHEMA)

    14       this.initDatabase();

    15   },

    16 

    17   initDatabase: function() {

    18     this.db.createTable("script",

    19                         "id INTEGER PRIMARY KEY AUTOINCREMENT," +

    20                         "name TEXT," +

    21                         "version TEXT," +

    22                         "author TEXT," +

    23                         "description TEXT," +

    24                         "uri TEXT," +

    25                         "enabled INTEGER," +

    26                         "script TEXT");

    27     this.db.createTable("include",

    28                         "script_id INTEGER," +

    29                         "address TEXT");

    30 

    31     this.db.executeSimpleSQL("CREATE TRIGGER delete_script AFTER DELETE ON script BEGIN " +

    32         "DELETE FROM include WHERE script_id=old.id; " +

    33       "END");

    34     this.db.schemaVersion = DB_SCHEMA;

    35   },

    36 

    37   getScript: function(aId) {

    38     if (aId.substring(aId.length - ID_SUFFIX.length) != ID_SUFFIX)

    39       return null;

    40 

    41     var stmt = this.db.createStatement("SELECT id, name, version, author, description, uri, enabled, script FROM script WHERE id=:id");

    42     stmt.params.id = aId.substring(0, aId.length - ID_SUFFIX.length);

    43     if (stmt.executeStep())

    44       return new Script(stmt.row);

    45     return null;

    46   },

    47 

    48   getAllScripts: function() {

    49     var scripts = [];

    50 

    51     var stmt = this.db.createStatement("SELECT id, name, version, author, description, uri, enabled, script FROM script");

    52     while (stmt.executeStep())

    53       scripts.push(new Script(stmt.row));

    54     return scripts;

    55   },

    56 

    57   getScriptsForURI: function(aURI) {

    58     var scripts = [];

    59 

    60     var stmt = this.db.createStatement("SELECT DISTINCT id, name, version, author, description, uri, enabled, script FROM script JOIN include ON script.id=include.script_id WHERE :uri GLOB address AND enabled=1");

    61     stmt.params.uri = aURI.spec;

    62     while (stmt.executeStep())

    63       scripts.push(new Script(stmt.row));

    64     return scripts;

    65   },

    66 

    67   hasScript: function(aURI) {

    68     var stmt = this.db.createStatement("SELECT COUNT() AS count FROM script WHERE uri=:uri");

    69     stmt.params.uri = aURI.spec;

    70 

    71     if (stmt.executeStep())

    72       return stmt.row.count > 0;

    73     return false;

    74   },

    75 

    76   installScript: function(aScript, aURI) {

    77     try {

    78       var data = {

    79         name: "",

    80         author: "",

    81         description: "",

    82         uri: aURI.spec,

    83         enabled: 1,

    84         script: aScript

    85       };

    86       var includes = [];

    87       var stmt = this.db.createStatement("INSERT INTO script VALUES (NULL, :name, :version, :author, :description, :uri, :enabled, :script)");

    88       stmt.params.uri = aURI.spec;

    89       stmt.params.enabled = 1;

    90       stmt.params.script = aScript;

    91 

    92       var start = aScript.indexOf("==UserScript==");

    93       var end = aScript.indexOf("==/UserScript==");

    94       if (start < 0 || end < 0)

    95         return;

    96 

    97       LOG("Looking for tags in " + aScript.substring(start, end));

    98       var lines = aScript.substring(start, end).split("\n");

    99       var pos = 0;

   100       while (pos < lines.length) {

   101         var matches = TAGMATCH.exec(lines[pos]);

   102         if (matches) {

   103           LOG("Tag: " + matches[1] + " = " + matches[2]);

   104           switch (matches[1]) {

   105           case "name":

   106           case "description":

   107           case "author":

   108           case "version":

   109             stmt.params[matches[1]] = matches[2];

   110             data[matches[1]] = matches[2];

   111             break;

   112           case "include":

   113             includes.push(matches[2]);

   114             break;

   115           }

   116         }

   117         pos++;

   118       }

   119 

   120       stmt.execute();

   121       var id = this.db.lastInsertRowID;

   122 

   123       stmt = this.db.createStatement("INSERT INTO include VALUES (:id, :address)");

   124       includes.forEach(function(aInclude) {

   125         stmt.params.id = id;

   126         stmt.params.address = aInclude;

   127         stmt.execute();

   128       });

   129 

   130       AddonManagerPrivate.callInstallListeners("onNewInstall", null,

   131                                                 new Script(data), null, false);

   132     }

   133     catch (e) {

   134       LOGE("Exception installing script", e);

   135     }

   136   },

   137 

   138   uninstallScript: function(aScript) {

   139     AddonManagerPrivate.callAddonListeners("onUninstalling", aScript, false);

   140     var stmt = this.db.createStatement("DELETE FROM script WHERE id=:id");

   141     stmt.params.id = aScript._id;

   142     stmt.execute();

   143     AddonManagerPrivate.callAddonListeners("onUninstalled", aScript);

   144   },

   145 

   146   updateDisabledState: function(aScript) {

   147     var stmt = this.db.createStatement("UPDATE script SET enabled=:enabled WHERE id=:id");

   148     stmt.params.id = aScript._id;

   149     stmt.params.enabled = aScript.enabled;

   150     stmt.execute();

   151   },

   152 

   153   shutdown: function() {

   154     this.db.asyncClose();

   155   }

   156 };

   157 

   158 function Script(aData) {

   159   this.id = aData.id + ID_SUFFIX;

   160   this._id = aData.id;

   161   this.name = aData.name;

   162   this.version = aData.version;

   163   this.creator = aData.author;

   164   this.description = aData.description;

   165   this.homepageURL = aData.uri;

   166   this.enabled = aData.enabled;

   167   this.script = aData.script;

   168 }

   169 

   170 Script.prototype = {

   171   _id: null,

   172   version: null,

   173   type: "user-script",

   174 

   175   isCompatible: true,

   176   providesUpdatesSecurely: true,

   177   blocklistState: 0,

   178   appDisabled: false,

   179   scope: AddonManager.SCOPE_PROFILE,

   180   isActive: true,

   181   pendingOperations: 0,

   182 

   183   name: null,

   184   version: null,

   185   description: null,

   186   creator: null,

   187   homepageURL: null,

   188 

   189   script: null,

   190 

   191   get userDisabled() {

   192     return this.enabled != 1;

   193   },

   194 

   195   set userDisabled(val) {

   196     if (val == this.userDisabled)

   197       return val;

   198 

   199     AddonManagerPrivate.callAddonListeners(val ? "onEnabling" : "onDisabling",

   200                                            this, false);

   201     this.enabled = val ? 0 : 1;

   202     ScriptDatabase.updateDisabledState(this);

   203     AddonManagerPrivate.callAddonListeners(val ? "onEnabled" : "onDisabled",

   204                                            this);

   205   },

   206 

   207   get permissions() {

   208     var perms = AddonManager.PERM_CAN_UNINSTALL;

   209     perms |= this.userDisabled ? AddonManager.PERM_CAN_ENABLE : AddonManager.PERM_CAN_DISABLE;

   210     return perms;

   211   },

   212 

   213   isCompatibleWith: function() {

   214     return true;

   215   },

   216 

   217   findUpdates: function(aListener) {

   218     if ("onNoCompatibilityUpdateAvailable" in aListener)

   219       aListener.onNoCompatibilityUpdateAvailable(this);

   220     if ("onNoUpdateAvailable" in aListener)

   221       aListener.onNoUpdateAvailable(this);

   222     if ("onUpdateFinished" in aListener)

   223       aListener.onUpdateFinished(this);

   224   },

   225 

   226   uninstall: function() {

   227     ScriptDatabase.uninstallScript(this);

   228   }

   229 };

   230 

   231 ScriptDatabase.startup();