之前我们确定了如何直接通过dispatch触发更新脚本
所以可以直接编写上传和更新的代码
async function setTMScript(uuid = "new-user-script", scriptContent) {
return new Promise((resolve, reject) => {
const isCreated = uuid === "new-user-script";
const sender = JSON.parse(fakeMessageSender);
if (!isCreated) {
sender.tab.url =
"chrome-extension://ppigooooicocpkikgggonplalbnnpkfj/options.html#nav=" +
uuid +
"+editor";
}
chrome.runtime.onMessage.dispatch(
{
auto_save: undefined,
clean: false,
code: scriptContent,
force: undefined,
lastModTime: isCreated ? undefined : new Date().getTime(),
method: "saveScript",
new_script: isCreated ? true : false,
reload: true,
restore: undefined,
uuid: uuid,
},
sender,
(response) => {
if (response.uuid !== undefined) {
//成功
resolve({ uuid: response.uuid });
} else {
//失败
reject();
}
}
);
});
}
然后在插件中声明一个socket监听发送脚本的数据,如果接收到了脚本就设置到油猴管理器中
var socket = io("http://<%= socketURL %>");
async function init() {
const scriptData = {};
socket.on("saveScript", (name, scriptContent) => {
console.log("saveScript", name, scriptContent);
setTMScript(scriptData[name], scriptContent)
.then(({ uuid }) => {
scriptData[name] = uuid;
socket.emit("saveScriptResult", "success", name);
})
.catch(() => {
socket.emit("saveScriptResult", "failed", name);
});
});
}
init();
目前新建脚本已经搞定了,但是修改脚本会触发tampermonkey的冲突提示
这个经过调试我没有找到太好的解决办法
但是可以利用dispatch投递消息解除掉这个弹窗
function allowAskCom(uuid) {
const form = {
method: "askCom",
data: {
aid: uuid,
message: undefined,
method: "install",
},
};
const sender = JSON.parse(fakeMessageSender);
chrome.runtime.onMessage.dispatch(form, sender, (response) => {
console.log("response", response);
});
}
但是必须在tabs开启后,所以可以对tabs.create做劫持,如果检测到ask.html启动就自动跳过
这里传入-1是因为根据调试必须给一个返回才能继续流程,而我们传入伪造的id,就会导致remove无法正常运行,所以必须也将remove劫持掉
const tabsCreate = chrome.tabs.create;
const tabsRemovce = chrome.tabs.remove;
chrome.tabs.remove = function (id, callback, ...args) {
if (id === -1) {
return;
}
const result = tabsCreate.call(this, id, callback, ...args);
return result;
};
chrome.tabs.create = function (obj, callback, ...args) {
const url = obj.url;
if (url.indexOf("ask.html?") !== -1) {
const uuid = url.split("aid=")[1];
allowAskCom(uuid);
//pass hook
callback({
id: -1,
});
return undefined;
}
const result = tabsCreate.call(this, obj, callback, ...args);
return result;
};
那我们在插件端的工作就大功搞成了,接下来只需要在本地发送脚本数据即可
function sendScriptContent(unionName, scriptContent) {
if (unionName === undefined) {
console.warn(unionName + "script unionName is not define");
return;
}
io.emit("saveScript", unionName, scriptContent);
}
其余的文件监听等等可以视为进一步的封装,我们就不继续谈了