`GM_listValues()` works again
[guerillascript.git] / main / modules / sbapi / scriptstorage.js
blob6fe6fa6a74f94fa29b95d5d9fbc54636255b69bf
1 /*
2  * Copyright 2004-2007 Aaron Boodman
3  * Portions copyright 2015 Ketmar Dark <ketmar@ketmar.no-ip.org>
4  * Contributors: See contributors list in install.rdf and CREDITS
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * Note that this license applies only to the Greasemonkey extension source
14  * files, not to the user scripts which it runs. User scripts are licensed
15  * separately by their authors.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  *
25  * The above copyright notice and this permission notice shall be included in all
26  * copies or substantial portions of the Software.
27  */
28 ////////////////////////////////////////////////////////////////////////////////
29 function ScriptStorage (nfo) {
30   this.dbBaseName = nfo.name;
31   this.dbObj = null;
32   return this;
36 ScriptStorage.prototype.__defineGetter__("dbFile", function () {
37   let file = getUserDBDir();
38   file.append(this.dbBaseName+".db");
39   return file;
40 });
43 ScriptStorage.prototype.__defineGetter__("db", function () {
44   if (this.dbObj == null) {
45     this.dbObj = Services.storage.openDatabase(this.dbFile);
46     // the auto_vacuum pragma has to be set before the table is created
47     //this.dbObj.executeSimpleSQL("PRAGMA auto_vacuum = INCREMENTAL;");
48     //this.dbObj.executeSimpleSQL("PRAGMA incremental_vacuum(10);");
49     this.dbObj.executeSimpleSQL("PRAGMA auto_vacuum = NONE;");
50     //this.dbObj.executeSimpleSQL("PRAGMA journal_mode = WAL;");
51     //this.dbObj.executeSimpleSQL("PRAGMA wal_autocheckpoint = 10;");
52     this.dbObj.executeSimpleSQL("PRAGMA journal_mode = DELETE;"); // will slow down bulk inserts, but IDC
53     this.dbObj.executeSimpleSQL(
54       "CREATE TABLE IF NOT EXISTS scriptvals ("+
55       "  name TEXT PRIMARY KEY NOT NULL,"+
56       "  value TEXT"+
57       ")"
58     );
59     // run vacuum once manually to switch to the correct auto_vacuum mode for
60     // databases that were created with incorrect auto_vacuum
61     this.dbObj.executeSimpleSQL("VACUUM;");
62   }
63   return this.dbObj;
64 });
67 ScriptStorage.prototype.__defineGetter__("opened", function () {
68   return (this.dbObj != null);
69 });
72 ScriptStorage.prototype.close = function () {
73   if (this.dbObj) {
74     this.dbObj.close();
75     this.dbObj = null;
76   }
80 ScriptStorage.prototype.setValue = function (name, val) {
81   if (arguments.length != 2) {
82     logError("invalid number of arguments to `GM_setValue()`");
83     throw new Error("invalid number of arguments to `GM_setValue()`");
84   }
85   if (val === null) {
86     this.deleteValue(name);
87     return;
88   }
89   //if (name === undefined) return;
90   //if (typeof(name) === "Object") return;
91   let stmt = this.db.createStatement("INSERT OR REPLACE INTO scriptvals (name, value) VALUES (:name, :value)");
92   try {
93     stmt.params.name = name;
94     stmt.params.value = JSON.stringify(val);
95     stmt.execute();
96   } finally {
97     stmt.reset();
98   }
102 ScriptStorage.prototype.getValue = function (name, defval) {
103   if (arguments.length < 1 || arguments.length > 2) {
104     logError("invalid number of arguments to `GM_getValue()`");
105     throw new Error("invalid number of arguments to `GM_getValue()`");
106   }
107   if (typeof(defval) === "undefined") defval = null;
108   let value = null;
109   let stmt = this.db.createStatement("SELECT value FROM scriptvals WHERE name = :name");
110   try {
111     stmt.params.name = name;
112     while (stmt.step()) value = stmt.row.value;
113   } catch (e) {
114     logException("GM_getValue", e);
115   } finally {
116     stmt.reset();
117   }
118   if (typeof(value) !== "string") return defval;
119   // parse json
120   try {
121     let exposedProps = "__exposedProps__";
122     value = JSON.parse(value);
123     if (typeof(value) == "object") {
124       if (!(exposedProps in value)) value[exposedProps] = {};
125       for (let prop in value) {
126         if (prop !== exposedProps && Object.prototype.hasOwnProperty.call(value, prop)) {
127           value[exposedProps][prop] = "rw"; // there is nothing wrong in making this r/w
128         }
129       }
130     }
131     return value;
132   } catch (e) {
133     //logError("JSON parse error: "+e.name+": "+e.message);
134     return defval;
135   }
139 ScriptStorage.prototype.deleteValue = function (name) {
140   if (arguments.length != 1) {
141     logError("invalid number of arguments to `GM_deleteValue()`");
142     throw new Error("invalid number of arguments to `GM_deleteValue()`");
143   }
144   let stmt = this.db.createStatement("DELETE FROM scriptvals WHERE name = :name");
145   try {
146     stmt.params.name = name;
147     stmt.execute();
148   } finally {
149     stmt.reset();
150   }
154 ScriptStorage.prototype.listValues = function () {
155   if (arguments.length != 0) {
156     logError("invalid number of arguments to `GM_listValues()`");
157     throw new Error("invalid number of arguments to `GM_listValues()`");
158   }
159   //let count = 0;
160   //let eprp = {length: "r"};
161   //let vals = {};
162   let valueNames = [];
163   let stmt = this.db.createStatement("SELECT name FROM scriptvals");
164   try {
165     while (stmt.executeStep()) {
166       valueNames.push(stmt.row.name);
167       //vals[count++] = stmt.row.name;
168     }
169   } finally {
170     stmt.reset();
171   }
172   //let vals = Array.prototype.slice.call(valueNames);
173   //vals.__exposedProps__ = {length: "r"};
174   //!vals.length = count;
175   //!vals.__exposedProps__ = eprp;
176   let vals = valueNames;
177   return vals;
181 ////////////////////////////////////////////////////////////////////////////////
182 exports.ScriptStorage = ScriptStorage;