当前位置: 首页 > news >正文

将Firefox插件导入Edge/Chrome中

目录

  • 将Firefox插件导入Edge/Chrome中
    • 前言
    • 导出火狐插件.xpi格式
    • 插件导入edge/chorme中
    • 错误示范1
    • 错误示范2
    • 修改过程
      • manifest.json
      • dict文件夹修改
        • backgroundScript.js
        • injectedScript.js
        • debug过程
        • 最终backgroundScript.js和injectedScript.js代码
    • 完工阶段
    • 修改后的源码

将Firefox插件导入Edge/Chrome中

前言

因为博主本人想在edge/chrome中使用cph-submit插件

  • vscode中cph,实现一键将代码提交到Codeforces
  • 但是只有firefox的插件
  • 另外两个比较麻烦,nodejs还有版本问题。

写这篇文章有三个原因:

  1. 网上暂且没找到firefox插件导入edge/chrome的方法

  2. 博主个人感觉这个debug过程比较有意义

  3. 也希望能帮助到其他人。

省流:最终可用的版本如下,直接下载解压开发人员模式导入edge插件即可:

  • https://wwf.lanzout.com/iJ3Gl21r9vja
  • 导入的流程可以见本文章节**“插件导入edge/chorme中”**
  • 可能还有点小bug,暂且没修好,但是能用(确信

导出火狐插件.xpi格式

在火狐浏览器中打开这个about:profiles,就可以看到了

  • 这就是你当前浏览器用户的存储文件夹

在这里插入图片描述

然后点击打开文件夹

点击extensions,进去就可以看到你安装的插件的.xpi格式,这边我只安装了一个(名为cph-submit)。

但是其实你可以通过修改时间来判断哪个是哪个(大不了卸掉再装一下,最新的那个)
Image

  • 一般也就一两个

然后把这个文件复制出来,找个空的目录放一下,我将它重命名为cph-submit.xpi

右键解压到文件夹(我用的360解压软件)

  • 这一步如果没法完成,你可以修改后缀名为.zip
  • 然后再解压,效果一样
    Image

因为解压完的文件夹不一定直接用

  • 有些 Firefox 扩展可能需要进行一些代码修改才能在 Edge/Chrome 上运行,
  • 需要修改 manifest.json 文件以符合 Edge/Chrome 的格式。

插件导入edge/chorme中

随后在edge/chrome浏览器中,打开开发人员模式

  • 进入edge://extensions/
  • Image

然后就会出现这些按钮

Image

如果修改好了最终的插件版本,就可以点击从“加载解压缩的扩展”

  • 也就是我刚刚发的
  • https://wwf.lanzout.com/iJ3Gl21r9vja
  • 这个解压缩后,导入进去

随后应该就可以用了,可以跳转到“完工阶段”查看效果

下面是错误示范,以及修改过程

错误示范1

不能用.crx格式导入

  • 不要将刚解压的文件夹的路径打包成为.crx格式,
  • 大概率会G掉

如下所示
在这里插入图片描述

选择解压后的路径

在这里插入图片描述

Image

随后就可以看到

Image

不过.crx才是我们要用的,.pem不需要

.crx直接拖进浏览器中,点击添加拓展

在这里插入图片描述

启动按键是灰色的,这是错误示范,所以不能这样

直接用解压好的就没下面这个问题

在这里插入图片描述

错误示范2

如果你修改的,有问题

  • 第一种情况,初始化的时候就有问题,那么一导入就是挂的

在这里插入图片描述

  • 第二种情况,运行到一半,用到才有问题

会先正常显示,然后在挂掉(错误/重新加载两个一开始不显示)

此时你其实可以点进去错误,查看哪里错了,然后修改

当然,一般修改工作量也挺大的

可以交给GPT来改

在这里插入图片描述
Image

这些错误是可以展开的,直到报错后针对性修改

(无关紧要的)提醒:

要是你不知道firefox和edge他们的manifest.json的差别,其实你可以本地找一下edge拓展的源文件,然后对比下

当然,我都喂给了GPT,让他帮忙修改

C:\Users\<你的电脑用户名>\AppData\Local\Microsoft\Edge\User Data\Default\Extensions

有问题的话,得删除插件

然后再从文件夹导入这个插件

修改过程

manifest.json

点进文件夹,查看manifest.json如下

{"name": "CPH Submit","manifest_version": 2,"homepage_url": "https://github.com/agrawal-d/cph-submit","version": "1.6.0","description": "Codeforces Submit add-on for Competitive Programming Helper.","background": {"scripts": ["dist/backgroundScript.js"]},"permissions": ["*://localhost/*", "*://codeforces.com/*", "webNavigation"],"icons": {"48": "icon-48.png"},"browser_specific_settings": {"gecko": {"id": "{5dd8fd6e-0733-41a7-abc4-e19fba703de9}","strict_min_version": "49.0"}}
}

我将其修改为:

  • manifest_version:
    • 2 改为 3
  • background:
    • scripts 改为 service_worker,并增加 "type": "module"
  • action:
    • 添加 action 部分,用于定义插件的图标和默认标题。
  • host_permissions:
    • 添加 host_permissionsoptional_host_permissions 来管理插件的权限。
  • 删除key字段:
    • 不再包含key字段,因为这是开发中的插件,不是发布到商店的版本。
  • permissions:
    • 保留 activeTabwebNavigationscripting 权限。
  • host_permissions:
    • 使用 host_permissions 来指定对 localhostcodeforces.com 的访问权限。
  • 删除 optional_host_permissions:
    • 移除 optional_host_permissions 字段,因为它包含的权限已经在 host_permissions 中。
{"name": "CPH Submit","manifest_version": 3,"homepage_url": "https://github.com/agrawal-d/cph-submit","version": "1.6.0","description": "Codeforces Submit add-on for Competitive Programming Helper.","background": {"service_worker": "dist/backgroundScript.js","type": "module"},"permissions": ["activeTab", "webNavigation", "scripting"],"icons": {"48": "icon-48.png"},"action": {"default_icon": {"48": "icon-48.png"},"default_title": "CPH Submit"},"host_permissions": ["*://localhost/*", "*://codeforces.com/*"]
}

dict文件夹修改

还需要修改解压文件夹中的dictbackgroundScript.jsinjectedScript.js

  • 并不能从火狐直接移植到chrome/edge
  • 里面的browser API 需要修改为chrome API
    • **Edge浏览器现在基于Chromium,所以使用与Chrome相同的API。**二者可以共享,但是与火狐不行
    • 因此,只需要将代码中的 browser 替换为 chrome,并使用 chrome.scripting.executeScript 来代替 browser.tabs.executeScript
  • 需要修改的地方可能还有
    • browser 替换为 chrome:所有 browser API 调用替换为 chrome
      • browser.tabs.create 修改为 chrome.tabs.create
      • browser.windows.update 修改为 chrome.windows.update
      • 使用 chrome.scripting.executeScript 代替 browser.tabs.executeScript
      • browser.tabs.sendMessage 修改为 chrome.tabs.sendMessage
backgroundScript.js

backgroundScript.js 是浏览器扩展的背景脚本,负责处理一些全局的后台任务,例如:

  1. 后台逻辑:处理定时任务、全局事件监听器等。
  2. 与服务器通信:从服务器获取数据,处理服务器响应。
  3. 管理浏览器标签页:创建、更新或关闭标签页。
  4. 在不同页面间传递消息:与内容脚本(如 injectedScript.js)进行通信。

在该扩展中,backgroundScript.js 主要负责从服务器获取提交信息,并在相应的 Codeforces 页面中自动提交代码。

代码在"最终backgroundScript.js和injectedScript.js代码"(

injectedScript.js

injectedScript.js 是注入到目标网页中的脚本,负责与网页内容进行交互,例如:

  1. 操作网页的 DOM:读取和修改网页中的元素,例如表单字段。
  2. 接收消息并执行操作:从背景脚本接收消息,并根据消息内容执行相应的操作。
  3. 模拟用户行为:自动填写表单、点击按钮等。

在该扩展中,injectedScript.js 主要负责在 Codeforces 提交页面上自动填写表单,并模拟用户点击提交按钮。

代码在"最终backgroundScript.js和injectedScript.js代码"(

debug过程

个人修改的debug过程

  • 解压文件夹中的dictbackgroundScript.jsinjectedScript.js

先将其改为最简单的.js,确保backgroundScript.js导入没问题

console.log('Service worker registered successfully');

监听下控制台
Image

看起来可以导入

逐渐加入代码

在这里插入图片描述

最终backgroundScript.js和injectedScript.js代码

最后backgroundScript.js修改结果如下

const config = {cphServerEndpoint: new URL("http://localhost:27121/getSubmit"),cfSubmitPage: new URL("https://codeforces.com/problemset/submit"),loopTimeOut: 3000,debug: false
};const log = (...args) => {if (config.debug) {console.log(...args);}
};const isContestProblem = (problemUrl) => {return problemUrl.indexOf("contest") !== -1;
};const getSubmitUrl = (problemUrl) => {if (!isContestProblem(problemUrl)) {return config.cfSubmitPage.href;}const url = new URL(problemUrl);const contestNumber = url.pathname.split("/")[2];const submitURL = `https://codeforces.com/contest/${contestNumber}/submit`;return submitURL;
};const handleSubmit = async (problemName, languageId, sourceCode, problemUrl) => {if (problemName === "" || languageId === -1 || sourceCode === "") {log("Invalid arguments to handleSubmit");return;}log("isContestProblem", isContestProblem(problemUrl));chrome.tabs.create({ active: true, url: getSubmitUrl(problemUrl) }, (tab) => {chrome.windows.update(tab.windowId, { focused: true });if (tab.id === undefined) {log("No tab id to send message to", tab);return;}chrome.tabs.onUpdated.addListener(function listener(tabId, changeInfo) {if (tabId === tab.id && changeInfo.status === 'complete') {chrome.tabs.onUpdated.removeListener(listener);chrome.scripting.executeScript({target: { tabId: tab.id },files: ["/dist/injectedScript.js"]}, () => {chrome.tabs.sendMessage(tab.id, {type: "cph-submit",problemName,languageId,sourceCode,url: problemUrl,}, () => {if (chrome.runtime.lastError) {console.error("Error sending message:", chrome.runtime.lastError);} else {log("Message sent to tab with script");}});});}});});
};const mainLoop = async () => {let cphResponse;try {const headers = new Headers();headers.append("cph-submit", "true");const request = new Request(config.cphServerEndpoint.href, {method: "GET",headers,});cphResponse = await fetch(request);} catch (err) {log("Error while fetching cph response", err);return;}if (!cphResponse.ok) {log("Error while fetching cph response", cphResponse);return;}const response = await cphResponse.json();if (response.empty) {log("Got empty valid response from CPH");return;}log("Got non-empty valid response from CPH");handleSubmit(response.problemName, response.languageId, response.sourceCode, response.url);
};setInterval(mainLoop, config.loopTimeOut);console.log('Service worker registered successfully');

以及injectedScript.js修改结果如下

console.log("cph-submit script injected");const isContestProblem = (problemUrl) => {return problemUrl.indexOf("contest") !== -1;
};const handleData = (data) => {console.log("Handling submit message");const languageEl = document.getElementsByName("programTypeId")[0];const sourceCodeEl = document.getElementById("sourceCodeTextarea");sourceCodeEl.value = data.sourceCode;languageEl.value = data.languageId.toString();if (!isContestProblem(data.url)) {const problemNameEl = document.getElementsByName("submittedProblemCode")[0];problemNameEl.value = data.problemName;} else {const problemIndexEl = document.getElementsByName("submittedProblemIndex")[0];let problemName = data.url.split("/problem/")[1];if (problemName == "0") {problemName = "A";}problemIndexEl.value = problemName;}console.log("Submitting problem");const submitBtn = document.querySelector(".submit");submitBtn.disabled = false;submitBtn.click();
};console.log("Adding event listener");chrome.runtime.onMessage.addListener((data, sender) => {console.log("Got message", data, sender);if (data.type === "cph-submit") {handleData(data);}
});

完工阶段

点击competitive Companion,将样例一键导入vscode中

Image

随后,在右侧编写代码

在这里插入图片描述

然后点击Submit提交代码

在这里插入图片描述

就成功在edge上,先自动跳转到提交界面,然后自动填写代码,提交表单

最后自动跳转到这个界面,提交成功

在这里插入图片描述

修改后的源码

上面其实也可以复制下来

我整理了可以直接用的版本

https://wwf.lanzout.com/iJ3Gl21r9vja

蓝奏云盘下载

相关文章:

  • Redis客户端界面工具QuickRedis
  • 6_1 Linux 用户管理
  • Cohere reranker 一致的排序器
  • 【论文复现|智能算法改进】基于改进鲸鱼优化算法的移动机器人多目标点路径规划
  • 1.Vue2使用ElementUI-初识及环境搭建
  • ViewModel、Lifecycles、LiveData基本使用
  • TK防关联引流系统:全球多账号运营,一“键”掌控!
  • Typora 破解、激活!亲测有效!2024 最新激活方法
  • 排序-快排算法对数组进行排序
  • 6-11 函数题:某范围中的最小值
  • 源代码防泄密经验分享之安全上网篇
  • 联邦学习的基本流程,联邦学习权重聚合,联邦学习权重更新
  • Serverless 使用OOS将http文件转存到对象存储
  • Spring的循环依赖
  • Vite - 项目打包从 0 到 1(完美解决打包后访问白屏问题)
  • 【知识碎片】第三方登录弹窗效果
  • 30天自制操作系统-2
  • Android Volley源码解析
  • Angular 响应式表单 基础例子
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • leetcode讲解--894. All Possible Full Binary Trees
  • mysql_config not found
  • mysql中InnoDB引擎中页的概念
  • python_bomb----数据类型总结
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • windows下如何用phpstorm同步测试服务器
  • 从0实现一个tiny react(三)生命周期
  • 飞驰在Mesos的涡轮引擎上
  • 机器学习 vs. 深度学习
  • 记一次删除Git记录中的大文件的过程
  • 智能网联汽车信息安全
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • const的用法,特别是用在函数前面与后面的区别
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • (2)STL算法之元素计数
  • (20050108)又读《平凡的世界》
  • (delphi11最新学习资料) Object Pascal 学习笔记---第14章泛型第2节(泛型类的类构造函数)
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (论文阅读11/100)Fast R-CNN
  • (三)终结任务
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (学习日记)2024.01.09
  • (转载)从 Java 代码到 Java 堆
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • ****** 二 ******、软设笔记【数据结构】-KMP算法、树、二叉树
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions
  • .net core使用ef 6
  • .NET技术成长路线架构图
  • .NET命名规范和开发约定
  • @select 怎么写存储过程_你知道select语句和update语句分别是怎么执行的吗?
  • [.net 面向对象程序设计进阶] (19) 异步(Asynchronous) 使用异步创建快速响应和可伸缩性的应用程序...
  • [autojs]逍遥模拟器和vscode对接
  • [BUUCTF]-Reverse:reverse3解析