Skip to content

Commit

Permalink
document-body & 沙盒优化
Browse files Browse the repository at this point in the history
  • Loading branch information
CodFrm committed Oct 7, 2021
1 parent b044e43 commit a879726
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 15 deletions.
5 changes: 4 additions & 1 deletion src/apps/grant/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,10 @@ export class BackgroundGrant {
if (xhr.readyState === 4) {
let contentType = xhr.getResponseHeader("Content-Type");
if ((!config.responseType && contentType && contentType.indexOf("application/json") !== -1)) {
respond.response = JSON.parse(xhr.responseText);
try {
respond.response = JSON.parse(xhr.responseText);
} catch (e) {
}
} else {
if (!respond.response && (config.responseType == "arraybuffer" || config.responseType == "blob")) {
if (xhr.response instanceof ArrayBuffer) {
Expand Down
4 changes: 2 additions & 2 deletions src/apps/grant/frontend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,14 @@ export class FrontendGrant implements ScriptContext {

public GM_info() {
return {
version: this.script.metadata['version'] && this.script.metadata['version'][0],
scriptWillUpdate: false,
scriptHandler: "ScriptCat",
scriptUpdateURL: this.script.origin,
scriptSource: this.script.code,
script: {
name: this.script.name,
namespace: this.script.namespace,
version: this.script.metadata['version'] && this.script.metadata['version'][0],
}
}
}
Expand Down Expand Up @@ -273,7 +273,7 @@ export class FrontendGrant implements ScriptContext {
ret = {
id: 0,
scriptId: this.script.id,
storageName: (this.script?.metadata['storagename'] && this.script?.metadata['storagename'][0]) || '',
storageName: (this.script.metadata['storagename'] && this.script.metadata['storagename'][0]) || '',
key: name,
value: value,
createtime: new Date().getTime()
Expand Down
38 changes: 37 additions & 1 deletion src/injected.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@ import { Value } from "./model/do/value";
import { addStyle } from "./pkg/frontend";
import { buildThis, createContext } from "./pkg/sandbox";

// 参考了tm的实现
function waitBody(callback: () => void) {
if (document.body) {
return callback();
}
let listen = function () {
document.removeEventListener('load', listen, false);
document.removeEventListener('DOMNodeInserted', listen, false);
document.removeEventListener('DOMContentLoaded', listen, false);
waitBody(callback);
};
document.addEventListener('load', listen, false);
document.addEventListener('DOMNodeInserted', listen, false);
document.addEventListener('DOMContentLoaded', listen, false);
};

let browserMsg = new BrowserMsg(ScriptFlag, false);
browserMsg.listen("scripts", (msg) => {
let scripts: ScriptCache[] = msg;
Expand Down Expand Up @@ -43,7 +59,27 @@ browserMsg.listen("scripts", (msg) => {
context = buildThis(window, context);
script.context = context;
}
if (script.metadata['run-at'] && script.metadata['run-at'][0] === 'document-menu') {
if (script.metadata['run-at'] && (script.metadata['run-at'][0] === 'document-menu' || script.metadata['run-at'][0] === 'document-body')) {
if (script.metadata['run-at'][0] === 'document-body') {
waitBody(() => {
if ((<any>window)[script.flag!]) {
(<any>window)[script.flag!].apply(context, [context]);
}
Object.defineProperty(window, script.flag!, {
get: () => { return undefined; },
set: (val) => {
val.apply(context, [context]);
}
});
// 注入css
script.metadata['require-css']?.forEach(val => {
let res = script.resource![val];
if (res) {
addStyle(res.content);
}
});
});
}
return;
}
if ((<any>window)[script.flag!]) {
Expand Down
37 changes: 28 additions & 9 deletions src/pkg/sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { ScriptCache, Script } from "@App/model/do/script";

export function compileScriptCode(script: ScriptCache): string {
let code = script.code;
let require = '';
script.metadata['require'] && script.metadata['require'].forEach((val) => {
let res = script.resource[val];
if (res) {
code = res.content + "\n" + code;
require = require + "\n" + res.content;
}
});
code = require + code;
return 'with (context) return (()=>{\n' + code + '\n})()'
}

Expand All @@ -23,35 +25,42 @@ export function buildWindow(): any {
}
}

let special: any = {
let writables: any = {
"addEventListener": global.addEventListener,
"removeEventListener": global.removeEventListener,
"dispatchEvent": global.dispatchEvent,
};

// 记录初始的
export let init = new Map<string, boolean>();

// 复制原有的,防止被前端网页复写
let descs = Object.getOwnPropertyDescriptors(global);
for (const key in descs) {
let desc = descs[key];
if (desc && desc.writable && !special[key]) {
special[key] = desc.value;
if (desc && desc.writable && !writables[key]) {
writables[key] = desc.value;
} else {
init.set(key, true);
}
}


// 处理有多层结构的(先只对特殊的做处理)
['console'].forEach(obj => {
let descs = Object.getOwnPropertyDescriptors((<any>global)[obj]);
special[obj] = {};// 清零
writables[obj] = {};// 清零
for (const key in descs) {
let desc = descs[key];
if (desc && desc.writable) {
special[obj][key] = desc.value;
writables[obj][key] = desc.value;
}
}
});

//TODO:做一些恶意操作拦截等
export function buildThis(global: any, context: any) {
let special = Object.assign({}, writables);
let proxy: any = new Proxy(context, {
defineProperty(_, name, desc) {
return Object.defineProperty(context, name, desc);
Expand All @@ -67,14 +76,15 @@ export function buildThis(global: any, context: any) {
if (context[name]) {
return context[name];
}
if (special[name]) {
if (special[name] !== undefined) {
if (typeof special[name] === 'function' && !special[name].prototype) {
return special[name].bind(global);
}
return special[name];
}
if (global[name]) {
if (global[name] !== undefined) {
if (typeof global[name] === 'function' && !global[name].prototype) {
console.log('b', name, global[name]);
return global[name].bind(global);
}
return global[name];
Expand All @@ -86,7 +96,16 @@ export function buildThis(global: any, context: any) {
return name == 'undefined' || context[name] || global.hasOwnProperty(name);
},
set(_, name: string, val) {
if (global[name] === null) {
if (special[name]) {
special[name] = val;
return true;
}
if (init.has(name)) {
let des = Object.getOwnPropertyDescriptor(global, name);
// 只读的return
if (des && des.get && !des.set && des.configurable) {
return true;
}
global[name] = val;
return true;
}
Expand Down
9 changes: 7 additions & 2 deletions tests/sandbox.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { buildThis } from "@App/pkg/sandbox";
import { buildThis, init } from "@App/pkg/sandbox";


describe("sandbox", () => {
let context: any = {};
let global: any = { onload: null };
let global: any = { gbok: 'gbok', onload: null };
init.set('onload', true);
let _this = buildThis(global, context);

it("set contenxt", () => {
Expand Down Expand Up @@ -31,5 +32,9 @@ describe("sandbox", () => {
expect(global['okk']).toEqual(undefined);
})

it("访问global的对象", () => {
expect(_this['gbok']).toEqual('gbok');
})

});

0 comments on commit a879726

Please sign in to comment.