Skip to content
Browse files

Implementing GM_watchValue and GM_unwatchValue. Closes #24

(cherry picked from commit 4d3e46e)
  • Loading branch information...
1 parent 241a764 commit 22fbde1c15812d6fdf50d3306016813b9a4f7358 @supahgreg supahgreg committed Sep 22, 2012
View
2 extension/locale/de/scriptish.properties
@@ -9,9 +9,11 @@ editor.prompt=Bitte erst den bevorzugten Texteditor wählen
editor.useScratchpad=
editor.useScratchpad.no=
editor.useScratchpad.yes=
+error.api.badArguments=
error.api.clipboard.type=ist kein von GM_setClipboard unterstützter Typ.
error.api.noResourceWithName=Keine Resource mit dem Namen
error.api.noSecondArgValue=Zweites Argument nicht spezifiziert: Value
+error.api.prefNotFound=
error.api.reqURL=Ungültige URL
error.api.reqURL.scheme=Verbotenes Schema (Protokoll) in URL
error.api.safeHTMLParser.url=
View
2 extension/locale/en-US/scriptish.properties
@@ -9,9 +9,11 @@ editor.prompt=Please choose your preferred text editor first
editor.useScratchpad=Do you want to use Scratchpad as your editor?
editor.useScratchpad.no=No (I will pick my own)
editor.useScratchpad.yes=Yes
+error.api.badArguments=Invalid or insufficient arguments were passed to a GM_ function.
error.api.clipboard.type=is not a type that is supported by GM_setClipboard.
error.api.noResourceWithName=No resource with name
error.api.noSecondArgValue=Second argument not specified: Value
+error.api.prefNotFound=An invalid or non-existent preference name was passed to a GM_ function.
error.api.reqURL=Invalid URL
error.api.reqURL.scheme=Disallowed scheme in URL
error.api.safeHTMLParser.url=The "URL" argument of GM_safeHTMLParser could not be parsed
View
2 extension/locale/es-ES/scriptish.properties
@@ -9,9 +9,11 @@ editor.prompt=Por favor, elija antes su editor de texto favorito
editor.useScratchpad=¿Desea usar Scratchpad como su editor?
editor.useScratchpad.no=No (yo seleccionaré el mío)
editor.useScratchpad.yes=Sí
+error.api.badArguments=
error.api.clipboard.type=no es un tipo soportado por GM_setClipboard.
error.api.noResourceWithName=No hay recursos con ese nombre
error.api.noSecondArgValue=Segundo argumento no especificado: Valor
+error.api.prefNotFound=
error.api.reqURL=URL no válido
error.api.reqURL.scheme=Esquema no permitido en URL
error.api.safeHTMLParser.url=
View
2 extension/locale/he/scriptish.properties
@@ -9,9 +9,11 @@ editor.prompt=אנא בחר תחילה את עורך הטקסט המועדף ע
editor.useScratchpad=האם ברצונך להשתמש ב־Scratchpad כעורך הטקסט שלך?
editor.useScratchpad.no=לא (אני אבחר בעצמי)
editor.useScratchpad.yes=כן
+error.api.badArguments=
error.api.clipboard.type=אינו מסוג שנתמך ע"י GM_setClipboard.
error.api.noResourceWithName=לא קיים משאב בעל שם
error.api.noSecondArgValue=לא צוין ערך שני: ערך
+error.api.prefNotFound=
error.api.reqURL=כתובת URL לא חוקית
error.api.reqURL.scheme=ערכה לא מורשת בכתובת URL
error.api.safeHTMLParser.url=
View
2 extension/locale/hu/scriptish.properties
@@ -9,9 +9,11 @@ editor.prompt=Kérem először válassza ki az Ön által preferált szerkesztő
editor.useScratchpad=A Scratchpad-et szeretné használni szerkesztőként?
editor.useScratchpad.no=Nem (kiválasztok egy sajátot)
editor.useScratchpad.yes=Igen
+error.api.badArguments=
error.api.clipboard.type=a GM_setClipboard által nem támogatott típus.
error.api.noResourceWithName=Nincs erőforrás ezen a néven:
error.api.noSecondArgValue=Második argumentum nincs meghatározva: Érték
+error.api.prefNotFound=
error.api.reqURL=Érvénytelen URL
error.api.reqURL.scheme=Az URL formátuma érvénytelen
error.api.safeHTMLParser.url=
View
2 extension/locale/ja-JP/scriptish.properties
@@ -9,9 +9,11 @@ editor.prompt=エディタを選択してください
editor.useScratchpad=エディタとしてスクラッチパッドを使用しますか?
editor.useScratchpad.no=No(自分でエディタを指定)
editor.useScratchpad.yes=Yes
+error.api.badArguments=
error.api.clipboard.type=は GM_setClipboard がサポートしていない型(type)です
error.api.noResourceWithName=名前付きリソースが見つかりません
error.api.noSecondArgValue=2番目の引数が指定されていません:Value
+error.api.prefNotFound=
error.api.reqURL=不正な URL です
error.api.reqURL.scheme=許可されていないスキーム(scheme)を URL で指定しています
error.api.safeHTMLParser.url=GM_safeHTMLParser の引数 "URL" をパース(parse)できません
View
2 extension/locale/pl/scriptish.properties
@@ -9,9 +9,11 @@ editor.prompt=Najpierw proszę wybrać swój preferowany edytor tekstu
editor.useScratchpad=Czy chcesz użyć Scratchpad-a jako edytor?
editor.useScratchpad.no=Nie ( sam wybiorę )
editor.useScratchpad.yes=Tak
+error.api.badArguments=
error.api.clipboard.type=nie jest to typ wspierany przez GM_setClipboard.
error.api.noResourceWithName=Brak źródeł z nazwą
error.api.noSecondArgValue=Drugi argument nie został określony: Wartość
+error.api.prefNotFound=
error.api.reqURL=Błędny URL
error.api.reqURL.scheme=Niedozwolony schemat URL
error.api.safeHTMLParser.url=
View
2 extension/locale/pt-BR/scriptish.properties
@@ -9,9 +9,11 @@ editor.prompt=Escolha seu editor de texto preferido
editor.useScratchpad=Você gostaria de usar o Scratchpad como seu editor?
editor.useScratchpad.no=Não (eu vou escolher outro)
editor.useScratchpad.yes=Sim
+error.api.badArguments=
error.api.clipboard.type=não é um tipo suportado por GM_setClipboard.
error.api.noResourceWithName=Nenhum recurso com o nome
error.api.noSecondArgValue=Segundo argumento não especificado: Valor
+error.api.prefNotFound=
error.api.reqURL=Endereço inválido
error.api.reqURL.scheme=Esquema não permitido em URL
error.api.safeHTMLParser.url=
View
2 extension/locale/ru-RU/scriptish.properties
@@ -9,9 +9,11 @@ editor.prompt=Пожалуйста, выберите ваш любимый ре
editor.useScratchpad=Вы хотите использовать Scratchpad в качестве редактора?
editor.useScratchpad.no=Нет (я выберу свой​​)
editor.useScratchpad.yes=Да
+error.api.badArguments=
error.api.clipboard.type=Тип данных не подходит для GM_setClipboard.
error.api.noResourceWithName=Нет ресурса с таким именем
error.api.noSecondArgValue=Второй аргумент - значение - не задан
+error.api.prefNotFound=
error.api.reqURL=Неверный URL
error.api.reqURL.scheme=Запрещённая схема в URL
error.api.safeHTMLParser.url=Не удалось разобрать аргумент «URL» из GM_safeHTMLParser
View
2 extension/locale/sv-SE/scriptish.properties
@@ -9,9 +9,11 @@ editor.prompt=Var vänlig välj först det textredigeringsprogram du föredrar
editor.useScratchpad=Vill du använda Scratchpad som din textredigerare?
editor.useScratchpad.no=Nej, jag väljer min egen
editor.useScratchpad.yes=Ja
+error.api.badArguments=
error.api.clipboard.type=är inte en typ som stöds av GM_setClipboard.
error.api.noResourceWithName=Det finns ingen resurs med namnet
error.api.noSecondArgValue=Det andra argumentet har inte angivits: Värde
+error.api.prefNotFound=
error.api.reqURL=Ogiltig URL
error.api.reqURL.scheme=Otillåtet schema i URL
error.api.safeHTMLParser.url=Argumentet "URL" för GM_safeHTMLParser kunde inte parsas
View
2 extension/locale/zh-CN/scriptish.properties
@@ -9,9 +9,11 @@ editor.prompt=请选择您喜欢的文本编辑器
editor.useScratchpad=您想使用暂存器作为您的编辑器吗?
editor.useScratchpad.no=不(我要选择我自己喜欢的)
editor.useScratchpad.yes=是
+error.api.badArguments=
error.api.clipboard.type=不是 GM_setClipboard 所支持的类型。
error.api.noResourceWithName=没有该名称的资源
error.api.noSecondArgValue=第二个参数未指定:值
+error.api.prefNotFound=
error.api.reqURL=无效的 URL
error.api.reqURL.scheme=不允许在 URL 中出现 scheme
error.api.safeHTMLParser.url=无法解释 GM_safeHTMLParser 函数的中的 URL参数
View
2 extension/locale/zh-TW/scriptish.properties
@@ -9,9 +9,11 @@ editor.prompt=請先選擇您常用的文字編輯器
editor.useScratchpad=您想使用程式碼片段速記本作為您的編輯器嗎?
editor.useScratchpad.no=不(我要自己選擇)
editor.useScratchpad.yes=是
+error.api.badArguments=
error.api.clipboard.type=不是 GM_setClipboard 所支援的類型。
error.api.noResourceWithName=沒有該名稱的資源
error.api.noSecondArgValue=第二個參數未指定:值
+error.api.prefNotFound=
error.api.reqURL=無效的網址
error.api.reqURL.scheme=網址中有不支援的協定
error.api.safeHTMLParser.url=
View
16 extension/modules/api.js
@@ -78,7 +78,7 @@ function GM_API(options) {
return new GM_xmlhttpRequester(aUnsafeContentWin, aURL, aScript);
});
lazy(lazyLoaders, "storage", function() {
- return new GM_ScriptStorage(aScript);
+ return new GM_ScriptStorage(aScript, aSafeWin);
});
lazy(lazyLoaders, "resources", function() {
return new GM_Resources(aScript);
@@ -152,6 +152,20 @@ function GM_API(options) {
if (!GM_apiLeakCheck("GM_deleteValue")) return;
return lazyLoaders.storage.deleteValue.apply(lazyLoaders.storage, arguments);
};
+ this.GM_watchValue = function GM_watchValue(aName, aListener) {
+ if (!GM_apiLeakCheck("GM_watchValue")) return;
+ let listener = null;
+ if ("function" === typeof aListener) {
+ listener = function(aEvent) {
+ GM_apiSafeCallback(aSafeWin, aScript, null, aListener, [aEvent]);
+ };
+ }
+ return lazyLoaders.storage.watchValue.call(lazyLoaders.storage, aName, listener);
+ }
+ this.GM_unwatchValue = function GM_unwatchValue() {
+ if (!GM_apiLeakCheck("GM_unwatchValue")) return;
+ return lazyLoaders.storage.unwatchValue.apply(lazyLoaders.storage, arguments);
+ }
this.GM_listValues = function GM_listValues() {
if (!GM_apiLeakCheck("GM_listValues")) return;
return lazyLoaders.storage.listValues.apply(lazyLoaders.storage, arguments);
View
104 extension/modules/api/GM_ScriptStorage.js
@@ -1,11 +1,26 @@
var EXPORTED_SYMBOLS = ["GM_ScriptStorage"];
-const Cu = Components.utils;
-Cu.import("resource://scriptish/prefmanager.js");
-Cu.import("resource://scriptish/utils/Scriptish_stringBundle.js");
+Components.utils.import("resource://scriptish/constants.js");
-function GM_ScriptStorage(script) {
- this.prefMan = new Scriptish_PrefManager(script.prefroot);
+lazyImport(this, "resource://scriptish/prefmanager.js", ["Scriptish_PrefManager"]);
+
+lazyUtil(this, "getWindowIDs");
+lazyUtil(this, "stringBundle");
+lazyUtil(this, "windowUnloader");
+
+function GM_ScriptStorage(aScript, aSafeWin) {
+ this.prefMan = new Scriptish_PrefManager(aScript.prefroot);
+ this._watchedPrefs = Object.create(null);
+
+ // Be sure to remove any watchers when the window unloads
+ let winID = Scriptish_getWindowIDs(aSafeWin).innerID;
+ Scriptish_windowUnloader(function() {
+ let prefChanged = this._prefChanged.bind(this);
+ for (let name in this._watchedPrefs) {
+ this.prefMan.unwatch(name, prefChanged);
+ delete this._watchedPrefs[name];
+ }
+ }.bind(this), winID);
}
GM_ScriptStorage.prototype.setValue = function(name, val) {
@@ -24,6 +39,85 @@ GM_ScriptStorage.prototype.deleteValue = function(name) {
return this.prefMan.remove(name);
};
+// Notifies any script watchers of a preference change
+GM_ScriptStorage.prototype._prefChanged = function(aName) {
+ if (!(aName in this._watchedPrefs)) {
+ return;
+ }
+ let newValue = this.getValue(aName);
+ let watchers = this._watchedPrefs[aName].watchers;
+ for (let i = 0, e = watchers.length; i < e; ++i) {
+ watchers[i].notify({
+ __exposedProps__: {
+ name: "r",
+ oldValue: "r",
+ newValue: "r"
+ },
+ "name": aName,
+ "oldValue": this._watchedPrefs[aName].currentValue,
+ "newValue": newValue
+ });
+ }
+ this._watchedPrefs[aName].currentValue = newValue;
+}
+
+GM_ScriptStorage.prototype.watchValue = function(aName, aListener) {
+ // Make sure we were passed everything
+ if (!(aName && aListener && "function" === typeof aListener)) {
+ throw new Error(Scriptish_stringBundle("error.api.badArguments"));
+ }
+
+ // Nothing to do if the preference doesn't exist
+ if (!this.prefMan.exists(aName)) {
+ throw new Error(Scriptish_stringBundle("error.api.prefNotFound"));
+ }
+
+ // Generate a UUID for the watcher so it can be unwatched by the user
+ let uuid = Services.uuid.generateUUID().toString();
+ let watcher = {"notify": aListener, "uuid": uuid};
+
+ // Add to existing watchers, or set up a new pref watcher
+ if (aName in this._watchedPrefs) {
+ this._watchedPrefs[aName].watchers.push(watcher);
+ }
+ else {
+ this._watchedPrefs[aName] = {
+ "currentValue": this.getValue(aName),
+ "watchers": [watcher]
+ };
+
+ // Start watching the pref
+ this.prefMan.watch(aName, this._prefChanged.bind(this));
+ }
+
+ // Return the watcher's UUID so it can be unwatched by the user
+ return uuid;
+};
+
+GM_ScriptStorage.prototype.unwatchValue = function(aName, aUUID) {
+ // Nothing to do if the preference doesn't exist or isn't watched
+ if (!(aName in this._watchedPrefs && this.prefMan.exists(aName))) {
+ return false;
+ }
+
+ let watchers = this._watchedPrefs[aName].watchers;
+
+ // If given a UUID, only remove the specified watcher
+ if (aUUID) {
+ for (let i = 0, e = watchers.length; i < e; ++i) {
+ if (aUUID === watchers[i].uuid) {
+ watchers.splice(i, 1);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Otherwise remove all watchers for the preference
+ watchers.length = 0;
+ return true;
+}
+
GM_ScriptStorage.prototype.listValues = function() {
return this.prefMan.listValues();
};

0 comments on commit 22fbde1

Please sign in to comment.
Something went wrong with that request. Please try again.