Skip to content
This repository
Browse code

Implementing GM_watchValue and GM_unwatchValue. Closes #24

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

0 comments on commit 22fbde1

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