error reporting cosmetix
[guerillascript.git] / modules / sandbox.js
bloba80c283be90122593db3c5e18fce12bd63b53ab7
1 /*
2 * Portions copyright 2004-2007 Aaron Boodman
3 * Copyright 2015 Ketmar Dark <ketmar@ketmar.no-ip.org>
4 * Contributors: See contributors list in install.rdf and CREDITS
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:
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.
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.
25 * The above copyright notice and this permission notice shall be included in all
26 * copies or substantial portions of the Software.
28 ////////////////////////////////////////////////////////////////////////////////
29 let {GuerillaXmlHttpReqester} = require("xmlhttprequest.js");
30 let {ScriptStorage} = require("storage.js");
31 let {openTab} = require("opentab.js");
34 ////////////////////////////////////////////////////////////////////////////////
35 let ioSvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
37 function uriFromUrl (url, base) {
38 let baseUri = null;
39 if (typeof(base) === "string") {
40 baseUri = uriFromUrl(base);
41 } else if (base) {
42 baseUri = base;
44 try {
45 return ioSvc.newURI(url, null, baseUri);
46 } catch (e) {
47 return null;
52 ////////////////////////////////////////////////////////////////////////////////
53 let pu = false;
55 function safeHTMLParser (domWin, htmlstr, baseUrl) {
56 //conlog("domWin: "+domWin);
57 //conlog("htmlstr: "+htmlstr);
58 //conlog("baseUrl: "+baseUrl);
59 let doc = domWin.document.implementation.createDocument("", "", domWin.document.implementation.createDocumentType("html", "", ""));
60 doc.appendChild(doc.createElement("html"));
61 doc.documentElement.appendChild(doc.createElement("body"));
63 let baseUri = null, frag;
64 if (typeof(baseUrl) !== "undefined") baseUri = uriFromUrl(baseUrl);
66 if (!pu) {
67 pu = Cc["@mozilla.org/parserutils;1"].createInstance(Ci.nsIParserUtils);
68 if (!pu) { logError("FUCKED!"); return null; }
70 frag = pu.parseFragment(htmlstr, 0, false, baseUri, doc.body);
71 doc.adoptNode(frag);
72 doc.body.appendChild(frag);
73 return doc;
77 ////////////////////////////////////////////////////////////////////////////////
78 let uuidgen = false;
80 function genUUID () {
81 if (!uuidgen) {
82 uuidgen = Cc["@mozilla.org/uuid-generator;1"].createInstance(Ci.nsIUUIDGenerator);
83 if (!uuidgen) throw new Error("no UUID generator available!");
85 return uuidgen.generateUUID().toString();
89 ////////////////////////////////////////////////////////////////////////////////
90 let storageObjects = {};
92 function getStorageObject (nfo) {
93 if (nfo.name in storageObjects) {
94 return storageObjects[nfo.name];
95 } else {
96 let res = new ScriptStorage(nfo);
97 storageObjects[nfo.name] = res;
98 return res;
103 exports.closeStorageObjects = function () {
104 for (let k in storageObjects) {
105 if (typeof(k) != "string") continue;
106 let dbo = storageObjects[k];
107 //if (typeof(dbo) != "object") continue;
108 if (dbo.opened) {
109 if (guerillaOptions.debugMode) conlog("freeing storage object for '"+k+"'");
110 dbo.close();
113 storageObjects = {};
117 ////////////////////////////////////////////////////////////////////////////////
118 exports.createSandbox = function (domWin, nfo, url) {
119 let sandbox;
121 if (nfo.unwrapped) {
122 // create "unwrapped" sandbox
123 sandbox = Cu.Sandbox(domWin, {
124 sandboxName: "unwrapped",
125 sandboxPrototype: domWin/*.wrappedJSObject*/,
126 wantXrays: false,
128 // alias unsafeWindow for compatibility
129 Cu.evalInSandbox("const unsafeWindow = window;", sandbox);
130 } else {
131 // create "real" sandbox
132 sandbox = Cu.Sandbox(domWin, {
133 sandboxName: nfo.name,
134 sandboxPrototype: domWin/*.wrappedJSObject*/,
135 wantXrays: true,
138 // Note that because waivers aren't propagated between origins, we need the
139 // unsafeWindow getter to live in the sandbox. See http://bugzil.la/1043958
140 let unsafeWindowGetter = new sandbox.Function("return (window.wrappedJSObject||window);");
141 Object.defineProperty(sandbox, "unsafeWindow", {get: unsafeWindowGetter});
143 sandbox.GM_generateUUID = genUUID;
144 sandbox.GM_cryptoHash = function () cryptoHash.apply(null, arguments);
146 //Object.defineProperty(sandbox, "GM_safeHTMLParser", {get: function () hitch(null, safeHTMLParser, domWin)});
147 sandbox.GM_safeHTMLParser = hitch(null, safeHTMLParser, domWin);
149 let scriptStorage = getStorageObject(nfo);
150 sandbox.GM_getValue = hitch(scriptStorage, "getValue");
151 sandbox.GM_setValue = hitch(scriptStorage, "setValue");
152 sandbox.GM_deleteValue = hitch(scriptStorage, "deleteValue");
153 sandbox.GM_listValues = hitch(scriptStorage, "listValues");
155 sandbox.GM_xmlhttpRequest = hitch(new GuerillaXmlHttpReqester(domWin, url, sandbox), "contentStartRequest");
157 sandbox.GM_addStyle = hitch(null, function (doc, cssstr) {
158 var head = doc.getElementsByTagName("head")[0];
159 if (head) {
160 var style = doc.createElement("style");
161 style.textContent = cssstr;
162 style.type = "text/css";
163 head.appendChild(style);
164 return style;
166 return null;
167 }, domWin.document);
169 sandbox.GM_openInTab = hitch(null, openTab, domWin);
171 // stubs
172 sandbox.GM_getResourceText = function () { logError("GM_getResourceText(): stub!"); };
173 sandbox.GM_getResourceURL = function () { logError("GM_getResourceURL(): stub!"); };
174 sandbox.GM_registerMenuCommand = function () { logError("GM_registerMenuCommand(): stub!"); };
175 sandbox.GM_setClipboard = function () { logError("GM_setClipboard(): stub!"); };
178 // provide log functions for both wrapped and unwrapped scripts
179 if (!nfo.unwrapped || nfo.wantLog) {
180 sandbox.conlog = conlog;
181 sandbox.logError = logError;
182 sandbox.GM_log = conlog;
185 return sandbox;
189 exports.runInSandbox = function (sandbox, nfo) {
190 // eval the code, with anonymous wrappers when/if appropriate
191 function evalLazyWrap (code, fileName) {
192 try {
193 Cu.evalInSandbox(code, sandbox, "ECMAv5", fileName, 1);
194 } catch (e) {
195 if ("return not in function" == e.message) {
196 // we never anon wrap unless forced to by a "return not in a function" error
197 logError("please, do not use `return` in top-level code in "+fileName+":"+e.lineNumber);
198 Cu.evalInSandbox("(function(){ "+code+"\n})()", sandbox, "ECMAv5", fileName, 1);
199 } else {
200 // otherwise raise
201 throw e;
206 // eval the code, with a try/catch to report errors cleanly
207 function evalNoThrow (code, fileName) {
208 try {
209 evalLazyWrap(code, fileName);
210 } catch (e) {
211 logException("UJS", e);
212 return false;
214 return true;
217 // eval libraries
218 for (let f = 0; f < nfo.libs.length; ++f) {
219 let lib = nfo.libs[f];
220 if (!evalNoThrow(lib.text, lib.path)) return;
223 // eval reqs
224 for (let f = 0; f < nfo.reqs.length; ++f) {
225 let req = nfo.reqs[f];
226 if (!evalNoThrow(req.text, req.path)) return;
229 // eval main script
230 evalNoThrow(nfo.text, nfo.path);