From 038e4f50145c194f38396afe1136c535cbf001e2 Mon Sep 17 00:00:00 2001 From: David Rosca Date: Mon, 25 May 2015 11:34:22 +0200 Subject: [PATCH] GreaseMonkey: Implement GM_ functions for userscripts --- src/plugins/GreaseMonkey/data/bootstrap.js | 97 ++++++------------- .../GreaseMonkey/data/bootstrap.min.js | 2 +- src/plugins/GreaseMonkey/data/values.js | 30 ++++++ src/plugins/GreaseMonkey/data/values.min.js | 1 + src/plugins/GreaseMonkey/gm_manager.cpp | 14 ++- src/plugins/GreaseMonkey/gm_manager.h | 5 +- src/plugins/GreaseMonkey/gm_script.cpp | 14 ++- src/plugins/GreaseMonkey/greasemonkey.qrc | 1 + 8 files changed, 87 insertions(+), 77 deletions(-) create mode 100644 src/plugins/GreaseMonkey/data/values.js create mode 100644 src/plugins/GreaseMonkey/data/values.min.js diff --git a/src/plugins/GreaseMonkey/data/bootstrap.js b/src/plugins/GreaseMonkey/data/bootstrap.js index d6b8159fe..fe3f6957c 100644 --- a/src/plugins/GreaseMonkey/data/bootstrap.js +++ b/src/plugins/GreaseMonkey/data/bootstrap.js @@ -1,45 +1,42 @@ -if(typeof GM_xmlhttpRequest === "undefined") { +if (typeof GM_xmlhttpRequest === "undefined") { GM_xmlhttpRequest = function(/* object */ details) { details.method = details.method.toUpperCase() || "GET"; - if(!details.url) { + if (!details.url) { throw("GM_xmlhttpRequest requires an URL."); } // build XMLHttpRequest object var oXhr = new XMLHttpRequest; // run it - if(oXhr) { - if("onreadystatechange" in details) - oXhr.onreadystatechange = function() { details.onreadystatechange(oXhr) }; - if("onload" in details) - oXhr.onload = function() { details.onload(oXhr) }; - if("onerror" in details) - oXhr.onerror = function() { details.onerror(oXhr) }; - - oXhr.open(details.method, details.url, true); - - if("headers" in details) - for(var header in details.headers) - oXhr.setRequestHeader(header, details.headers[header]); - - if("data" in details) - oXhr.send(details.data); - else - oXhr.send(); - } else - throw ("This Browser is not supported, please upgrade.") + if("onreadystatechange" in details) + oXhr.onreadystatechange = function() { details.onreadystatechange(oXhr) }; + if("onload" in details) + oXhr.onload = function() { details.onload(oXhr) }; + if("onerror" in details) + oXhr.onerror = function() { details.onerror(oXhr) }; + + oXhr.open(details.method, details.url, true); + + if("headers" in details) + for(var header in details.headers) + oXhr.setRequestHeader(header, details.headers[header]); + + if("data" in details) + oXhr.send(details.data); + else + oXhr.send(); } } -if(typeof GM_addStyle === "undefined") { - function GM_addStyle(/* String */ styles) { +if (typeof GM_addStyle === "undefined") { + function GM_addStyle(/* string */ styles) { var head = document.getElementsByTagName("head")[0]; if (head === undefined) { document.onreadystatechange = function() { if (document.readyState == "interactive") { var oStyle = document.createElement("style"); - oStyle.setAttribute("type", "text\/css"); + oStyle.setAttribute("type", "text/css"); oStyle.appendChild(document.createTextNode(styles)); document.getElementsByTagName("head")[0].appendChild(oStyle); } @@ -47,54 +44,29 @@ if(typeof GM_addStyle === "undefined") { } else { var oStyle = document.createElement("style"); - oStyle.setAttribute("type", "text\/css"); + oStyle.setAttribute("type", "text/css"); oStyle.appendChild(document.createTextNode(styles)); head.appendChild(oStyle); } } } -if(typeof GM_log === "undefined") { +if (typeof GM_log === "undefined") { function GM_log(log) { if(console) console.log(log); } } -if(typeof GM_openInTab === "undefined") { +if (typeof GM_openInTab === "undefined") { function GM_openInTab(url) { return window.open(url); } } -if(typeof GM_setClipboard === "undefined") { +if (typeof GM_setClipboard === "undefined") { function GM_setClipboard(text) { - window._qz_greasemonkey.setClipboard(text); - } -} - -// GM Settings Impl -if(typeof GM_getValueImpl === "undefined") { - function GM_getValueImpl(namespace, name, value) { - return window._qz_greasemonkey.getValue(namespace, name, value); - } -} - -if(typeof GM_setValueImpl === "undefined") { - function GM_setValueImpl(namespace, name, value) { - window._qz_greasemonkey.setValue(namespace, name, value); - } -} - -if(typeof GM_deleteValueImpl === "undefined") { - function GM_deleteValueImpl(namespace, name) { - window._qz_greasemonkey.deleteValue(namespace, name); - } -} - -if(typeof GM_listValuesImpl === "undefined") { - function GM_listValuesImpl(namespace) { - return window._qz_greasemonkey.listValues(namespace); + //window._qz_greasemonkey.setClipboard(text); } } @@ -103,19 +75,6 @@ var unsafeWindow = window; window.wrappedJSObject = unsafeWindow; // GM_registerMenuCommand not supported -if(typeof GM_registerMenuCommand === "undefined") { +if (typeof GM_registerMenuCommand === "undefined") { function GM_registerMenuCommand(caption, commandFunc, accessKey) { } } - -// GM Resource not supported -if(typeof GM_getResourceText === "undefined") { - function GM_getResourceText(resourceName) { - throw ("QupZilla: GM Resource is not supported!"); - } -} - -if(typeof GM_getResourceURL === "undefined") { - function GM_getResourceURL(resourceName) { - throw ("QupZilla: GM Resource is not supported!"); - } -} diff --git a/src/plugins/GreaseMonkey/data/bootstrap.min.js b/src/plugins/GreaseMonkey/data/bootstrap.min.js index 29cf3b70a..7ea61f3bc 100644 --- a/src/plugins/GreaseMonkey/data/bootstrap.min.js +++ b/src/plugins/GreaseMonkey/data/bootstrap.min.js @@ -1 +1 @@ -"undefined"===typeof GM_xmlhttpRequest&&(GM_xmlhttpRequest=function(a){a.method=a.method.toUpperCase()||"GET";if(!a.url)throw"GM_xmlhttpRequest requires an URL.";var b=new XMLHttpRequest;if(b){"onreadystatechange"in a&&(b.onreadystatechange=function(){a.onreadystatechange(b)});"onload"in a&&(b.onload=function(){a.onload(b)});"onerror"in a&&(b.onerror=function(){a.onerror(b)});b.open(a.method,a.url,!0);if("headers"in a)for(var c in a.headers)b.setRequestHeader(c,a.headers[c]);"data"in a?b.send(a.data): b.send()}else throw"This Browser is not supported, please upgrade.";}); if("undefined"===typeof GM_addStyle)var GM_addStyle=function(a){var b=document.getElementsByTagName("head")[0];if(void 0===b)document.onreadystatechange=function(){if("interactive"==document.readyState){var b=document.createElement("style");b.setAttribute("type","text/css");b.appendChild(document.createTextNode(a));document.getElementsByTagName("head")[0].appendChild(b)}};else{var c=document.createElement("style");c.setAttribute("type","text/css");c.appendChild(document.createTextNode(a));b.appendChild(c)}}; if("undefined"===typeof GM_log)var GM_log=function(a){console&&console.log(a)};if("undefined"===typeof GM_openInTab)var GM_openInTab=function(a){return window.open(a)};if("undefined"===typeof GM_setClipboard)var GM_setClipboard=function(a){window._qz_greasemonkey.setClipboard(a)};if("undefined"===typeof GM_getValueImpl)var GM_getValueImpl=function(a,b,c){return window._qz_greasemonkey.getValue(a,b,c)}; if("undefined"===typeof GM_setValueImpl)var GM_setValueImpl=function(a,b,c){window._qz_greasemonkey.setValue(a,b,c)};if("undefined"===typeof GM_deleteValueImpl)var GM_deleteValueImpl=function(a,b){window._qz_greasemonkey.deleteValue(a,b)};if("undefined"===typeof GM_listValuesImpl)var GM_listValuesImpl=function(a){return window._qz_greasemonkey.listValues(a)};var unsafeWindow=window;window.wrappedJSObject=unsafeWindow; if("undefined"===typeof GM_registerMenuCommand)var GM_registerMenuCommand=function(a,b,c){};if("undefined"===typeof GM_getResourceText)var GM_getResourceText=function(a){throw"QupZilla: GM Resource is not supported!";};if("undefined"===typeof GM_getResourceURL)var GM_getResourceURL=function(a){throw"QupZilla: GM Resource is not supported!";}; \ No newline at end of file +"undefined"===typeof GM_xmlhttpRequest&&(GM_xmlhttpRequest=function(a){a.method=a.method.toUpperCase()||"GET";if(!a.url)throw"GM_xmlhttpRequest requires an URL.";var b=new XMLHttpRequest;"onreadystatechange"in a&&(b.onreadystatechange=function(){a.onreadystatechange(b)});"onload"in a&&(b.onload=function(){a.onload(b)});"onerror"in a&&(b.onerror=function(){a.onerror(b)});b.open(a.method,a.url,!0);if("headers"in a)for(var c in a.headers)b.setRequestHeader(c,a.headers[c]);"data"in a?b.send(a.data):b.send()});if("undefined"===typeof GM_addStyle)var GM_addStyle=function(a){var b=document.getElementsByTagName("head")[0];if(void 0===b)document.onreadystatechange=function(){if("interactive"==document.readyState){var b=document.createElement("style");b.setAttribute("type","text/css");b.appendChild(document.createTextNode(a));document.getElementsByTagName("head")[0].appendChild(b)}};else{var c=document.createElement("style");c.setAttribute("type","text/css");c.appendChild(document.createTextNode(a));b.appendChild(c)}};if("undefined"===typeof GM_log)var GM_log=function(a){console&&console.log(a)};if("undefined"===typeof GM_openInTab)var GM_openInTab=function(a){return window.open(a)};if("undefined"===typeof GM_setClipboard)var GM_setClipboard=function(a){};var unsafeWindow=window;window.wrappedJSObject=unsafeWindow;if("undefined"===typeof GM_registerMenuCommand)var GM_registerMenuCommand=function(a,b,c){}; \ No newline at end of file diff --git a/src/plugins/GreaseMonkey/data/values.js b/src/plugins/GreaseMonkey/data/values.js new file mode 100644 index 000000000..637c288dd --- /dev/null +++ b/src/plugins/GreaseMonkey/data/values.js @@ -0,0 +1,30 @@ +// Modified from https://gist.githubusercontent.com/arantius/3123124/raw/grant-none-shim.js +// +// %1 - unique script id + +function GM_deleteValue(aKey) { + localStorage.removeItem("%1" + aKey); +} + +function GM_getValue(aKey, aDefault) { + var val = localStorage.getItem("%1" + aKey) + if (null === val && 'undefined' != typeof aDefault) return aDefault; + return val; +} + +function GM_listValues() { + var prefixLen = "%1".length; + var values = []; + var i = 0; + for (var i = 0; i < localStorage.length; i++) { + var k = localStorage.key(i); + if (k.substr(0, prefixLen) === "%1") { + values.push(k.substr(prefixLen)); + } + } + return values; +} + +function GM_setValue(aKey, aVal) { + localStorage.setItem("%1" + aKey, aVal); +} diff --git a/src/plugins/GreaseMonkey/data/values.min.js b/src/plugins/GreaseMonkey/data/values.min.js new file mode 100644 index 000000000..d10c11965 --- /dev/null +++ b/src/plugins/GreaseMonkey/data/values.min.js @@ -0,0 +1 @@ +function GM_deleteValue(b){localStorage.removeItem("%1"+b)}function GM_getValue(b,a){var c=localStorage.getItem("%1"+b);return null===c&&"undefined"!=typeof a?a:c}function GM_listValues(){for(var b=[],a=0,a=0;asetSettingsFile(m_settingsPath + QL1S("/extensions.ini")); } diff --git a/src/plugins/GreaseMonkey/gm_manager.h b/src/plugins/GreaseMonkey/gm_manager.h index 570f483e5..5064d97b4 100644 --- a/src/plugins/GreaseMonkey/gm_manager.h +++ b/src/plugins/GreaseMonkey/gm_manager.h @@ -44,6 +44,8 @@ public: QString settinsPath() const; QString scriptsDirectory() const; QString requireScripts(const QStringList &urlList) const; + QString bootstrapScript() const; + QString valuesScript() const; void unloadPlugin(); @@ -72,7 +74,8 @@ private slots: private: QString m_settingsPath; - QString m_bootstrap; + QString m_bootstrapScript; + QString m_valuesScript; QPointer m_settings; QStringList m_disabledScripts; diff --git a/src/plugins/GreaseMonkey/gm_script.cpp b/src/plugins/GreaseMonkey/gm_script.cpp index 10571599d..cce583d14 100644 --- a/src/plugins/GreaseMonkey/gm_script.cpp +++ b/src/plugins/GreaseMonkey/gm_script.cpp @@ -187,6 +187,9 @@ void GM_Script::parseScript() m_exclude.clear(); m_downloadUrl.clear(); m_startAt = DocumentEnd; + m_noframes = false; + m_script.clear(); + m_metadata.clear(); m_enabled = true; m_valid = false; @@ -275,11 +278,9 @@ void GM_Script::parseScript() int index = fileData.indexOf(QLatin1String("// ==/UserScript==")) + 18; m_metadata = fileData.mid(0, index); - QString script = fileData.mid(index).trimmed(); + const QString script = fileData.mid(index).trimmed(); m_valid = !script.isEmpty(); - m_script = QSL("(function(){%1\n%2\n})();").arg(m_manager->requireScripts(requireList), script); - #if QTWEBENGINE_DISABLED QString jscript("(function(){" "function GM_getValue(name,val){return GM_getValueImpl('%1',name,val);}" @@ -287,13 +288,16 @@ void GM_Script::parseScript() "function GM_deleteValue(name){return GM_deleteValueImpl('%1',name);}" "function GM_listValues(){return GM_listValuesImpl('%1');}" "\n%2\n})();"); - QString nspace = QCryptographicHash::hash(fullName().toUtf8(), QCryptographicHash::Md4).toHex(); #endif + const QString nspace = QCryptographicHash::hash(fullName().toUtf8(), QCryptographicHash::Md4).toHex(); + const QString gmValues = m_manager->valuesScript().arg(nspace); + + m_script = QSL("(function(){%1\n%2\n%3\n})();").arg(gmValues, m_manager->requireScripts(requireList), script); // Create QWebEngineScript m_webScript.setName(fullName()); m_webScript.setInjectionPoint(startAt() == DocumentStart ? QWebEngineScript::DocumentCreation : QWebEngineScript::DocumentReady); m_webScript.setWorldId(QWebEngineScript::MainWorld); m_webScript.setRunsOnSubFrames(!m_noframes); - m_webScript.setSourceCode(QSL("%1\n%2").arg(m_metadata, m_script)); + m_webScript.setSourceCode(QSL("%1\n%2\n%3").arg(m_metadata, m_manager->bootstrapScript(), m_script)); } diff --git a/src/plugins/GreaseMonkey/greasemonkey.qrc b/src/plugins/GreaseMonkey/greasemonkey.qrc index ae966a39f..586675147 100644 --- a/src/plugins/GreaseMonkey/greasemonkey.qrc +++ b/src/plugins/GreaseMonkey/greasemonkey.qrc @@ -1,6 +1,7 @@ data/bootstrap.min.js + data/values.min.js data/icon.png data/icon16.png data/icon18.png