将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还有版本问题。
写这篇文章有三个原因:
-
网上暂且没找到firefox插件导入edge/chrome的方法
-
博主个人感觉这个debug过程比较有意义
-
也希望能帮助到其他人。
省流:最终可用的版本如下,直接下载解压,开发人员模式导入edge插件即可:
- https://wwf.lanzout.com/iJ3Gl21r9vja
- 导入的流程可以见本文章节**“插件导入edge/chorme中”**
- 可能还有点小bug,暂且没修好,但是能用(确信
导出火狐插件.xpi格式
在火狐浏览器中打开这个about:profiles,就可以看到了
- 这就是你当前浏览器用户的存储文件夹

然后点击打开文件夹
点击extensions,进去就可以看到你安装的插件的.xpi格式,这边我只安装了一个(名为cph-submit)。
但是其实你可以通过修改时间来判断哪个是哪个(大不了卸掉再装一下,最新的那个)

- 一般也就一两个
然后把这个文件复制出来,找个空的目录放一下,我将它重命名为cph-submit.xpi
右键解压到文件夹(我用的360解压软件)
- 这一步如果没法完成,你可以修改后缀名为
.zip - 然后再解压,效果一样

因为解压完的文件夹不一定直接用
- 有些 Firefox 扩展可能需要进行一些代码修改才能在 Edge/Chrome 上运行,
- 需要修改
manifest.json文件以符合 Edge/Chrome 的格式。
插件导入edge/chorme中
随后在edge/chrome浏览器中,打开开发人员模式
- 进入
edge://extensions/ 
然后就会出现这些按钮

如果修改好了最终的插件版本,就可以点击从“加载解压缩的扩展”
- 也就是我刚刚发的
- https://wwf.lanzout.com/iJ3Gl21r9vja
- 这个解压缩后,导入进去
随后应该就可以用了,可以跳转到“完工阶段”查看效果
下面是错误示范,以及修改过程
错误示范1
不能用.crx格式导入
- 不要将刚解压的文件夹的路径打包成为
.crx格式, - 大概率会G掉
如下所示

选择解压后的路径


随后就可以看到

不过.crx才是我们要用的,.pem不需要
将.crx直接拖进浏览器中,点击添加拓展

启动按键是灰色的,这是错误示范,所以不能这样
直接用解压好的就没下面这个问题

错误示范2
如果你修改的,有问题
- 第一种情况,初始化的时候就有问题,那么一导入就是挂的

- 第二种情况,运行到一半,用到才有问题
会先正常显示,然后在挂掉(错误/重新加载两个一开始不显示)
此时你其实可以点进去错误,查看哪里错了,然后修改
当然,一般修改工作量也挺大的
可以交给GPT来改


这些错误是可以展开的,直到报错后针对性修改
(无关紧要的)提醒:
要是你不知道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_permissions和optional_host_permissions来管理插件的权限。
- 添加
- 删除key字段:
- 不再包含key字段,因为这是开发中的插件,不是发布到商店的版本。
- permissions:
- 保留
activeTab、webNavigation和scripting权限。
- 保留
- host_permissions:
- 使用
host_permissions来指定对localhost和codeforces.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文件夹修改
还需要修改解压文件夹中的dict的backgroundScript.js和injectedScript.js
- 并不能从火狐直接移植到
chrome/edge - 里面的
browserAPI 需要修改为chromeAPI- **Edge浏览器现在基于Chromium,所以使用与Chrome相同的API。**二者可以共享,但是与火狐不行
- 因此,只需要将代码中的
browser替换为chrome,并使用chrome.scripting.executeScript来代替browser.tabs.executeScript。
- 需要修改的地方可能还有
- 将
browser替换为chrome:所有browserAPI 调用替换为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 是浏览器扩展的背景脚本,负责处理一些全局的后台任务,例如:
- 后台逻辑:处理定时任务、全局事件监听器等。
- 与服务器通信:从服务器获取数据,处理服务器响应。
- 管理浏览器标签页:创建、更新或关闭标签页。
- 在不同页面间传递消息:与内容脚本(如
injectedScript.js)进行通信。
在该扩展中,backgroundScript.js 主要负责从服务器获取提交信息,并在相应的 Codeforces 页面中自动提交代码。
代码在"最终backgroundScript.js和injectedScript.js代码"(
injectedScript.js
injectedScript.js 是注入到目标网页中的脚本,负责与网页内容进行交互,例如:
- 操作网页的 DOM:读取和修改网页中的元素,例如表单字段。
- 接收消息并执行操作:从背景脚本接收消息,并根据消息内容执行相应的操作。
- 模拟用户行为:自动填写表单、点击按钮等。
在该扩展中,injectedScript.js 主要负责在 Codeforces 提交页面上自动填写表单,并模拟用户点击提交按钮。
代码在"最终backgroundScript.js和injectedScript.js代码"(
debug过程
个人修改的debug过程
- 解压文件夹中的
dict的backgroundScript.js和injectedScript.js
先将其改为最简单的.js,确保backgroundScript.js导入没问题
console.log('Service worker registered successfully');
监听下控制台

看起来可以导入
逐渐加入代码

最终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中

随后,在右侧编写代码

然后点击Submit提交代码

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

修改后的源码
上面其实也可以复制下来
我整理了可以直接用的版本
https://wwf.lanzout.com/iJ3Gl21r9vja
蓝奏云盘下载
相关文章:
将Firefox插件导入Edge/Chrome中
目录 将Firefox插件导入Edge/Chrome中前言导出火狐插件.xpi格式插件导入edge/chorme中错误示范1错误示范2修改过程manifest.jsondict文件夹修改backgroundScript.jsinjectedScript.jsdebug过程最终backgroundScript.js和injectedScript.js代码 完工阶段修改后的源码 将Firefox插…...
云计算【第一阶段(14)】Linux的目录和结构
一、Liunx目录结构 1.1、linux目录结构 linux目录结构是树形目录结构 根目录(树根) 所有分区,目录,文件等的位置起点整个树形目录结构中,使用独立的一个"/",表示 1.2、常见的子目录 必须知道 目录路径目…...
Zynq学习笔记--AXI4-Stream到视频输出IP是如何工作的?
目录 1. 简介 2. 原理详解 2.1 示例工程 2.2 AXI4-Stream to Video Out 3. Master/Slave Timing Mode 3.1 Slave Timing Mode 3.2 Master Timing Mode 4. 总结 1. 简介 本文主要介绍了 AXI4-Stream 到视频输出 的内容。其中,示例工程展示了一个具体的设计&…...
2016-2023 年美国农业部作物序列边界
简介 2016-2023 年美国农业部作物序列边界 作物序列边界(CSB)是与美国农业部经济研究局合作开发的,它提供了美国毗连地区的田间边界、作物种植面积和作物轮作的估计数据。该数据集利用卫星图像和其他公共数据,并且是开放源码的,使用户能够对美国种植的商品进行面积和统计…...
数字人源码部署怎么做?如何高效搭建好用的数字人系统?
作为人工智能时代的风口项目,AI数字人自出现之日起便引发了大量的关注。不少创业者都有了搭建数字人系统的想法,但却苦于没有强大的专业背景和雄厚资金支撑,只能在局外徘徊,而这恰恰为数字人源码公司推出的数字人源码部署服务的火…...
解决虚拟机Ubuntu IP总是掉的问题
问题 嵌入式开发过程中,需要使用NFS/TFTP等等,虚拟机Ubuntu就需要和板卡进行网络连接,但是我发现虚拟机Ubuntu的IP地址经常动不动就掉线,本文记录解决该问题的一些思路。 其实这个问题很简单,我早该想到,…...
[13] CUDA_Opencv联合编译过程
CUDA_Opencv联合编译过程 详细编译过程可见我之前的文章:Win10下OpencvCUDA联合编译详细教程(版本455、460、470,亲测可用!!!)本文给出Windows\linux下的opencvcuda的编译总结,摘自 <基于GP…...
uni-app canvas创建画布
canvasTmp: function(arr2, store_name, successFn, errFun) {let that this;const ctx uni.createCanvasContext(myCanvas);ctx.clearRect(0, 0, 0, 0);/*** 只能获取合法域名下的图片信息,本地调试无法获取* */uni.getImageInfo({ src: arr2[0],success: function(res) {…...
Spring MVC详解(上)
一、Spring MVC初步认识 1.1介绍 Spring MVC是Spring Framework提供的Web组件,全称是Spring Web MVC,是目前主流的实现MVC设计模式的框架,提供前端路由映射、视图解析等功能 Java Web开发者必须要掌握的技术框架 1.2MVC是什么 MVC是一种软件架构思想…...
【Linux硬盘读取】Windows下读取Linux系统的文件解决方案:Linux Reader4.5 By DiskInternals
前言 相信做机器视觉相关的很多人都会安装 Windows 和 Linux 双系统。在 Linux 下,我们可以很方便的访问Windows的磁盘,反过来却不行。但是这又是必须的。通过亲身体验,向大家推荐这么一个工具,可以让 Windows 方便的访问 Ext 2/3…...
操作系统—页表(实验)
文章目录 页表1.实验目标2.实验过程记录(1).增加打印页表函数(2).独立内核页表(3).简化软件模拟地址翻译 3.实验问题及相应解答问题1问题2问题3问题4 实验小结 页表 1.实验目标 了解xv6内核当中页表的实现原理,修改页表,使内核更方便地进行用户虚拟地址…...
github 本地仓库上传及报错处理
一.本地文件上传 这里为上传部分,关于gitbash安装配置,读者可自行搜索,由于已经安装完成,未进行截图保存,这里便不做赘述。 1.登录git账号并创建一个仓库 点击仓库打开后会看到这个仓库的网址链接(这个链…...
【ZZULIOJ】1104: 求因子和(函数专题)
题目描述 输入正整数n(2<n<1000),计算并输出n的所有正因子(包括1,不包括自身)之和。要求程序定义一个FacSum ()函数和一个main()函数,FacSum ()函数计算并返回n的所有正因子之和,其余功能在main()函…...
轨迹优化 | 图解欧氏距离场与梯度场算法(附ROS C++/Python实现)
目录 0 专栏介绍1 什么是距离场?2 欧氏距离场计算原理3 双线性插值与欧式梯度场4 仿真实现4.1 ROS C实现4.2 Python实现 0 专栏介绍 🔥课程设计、毕业设计、创新竞赛、学术研究必备!本专栏涉及更高阶的运动规划算法实战:曲线生成…...
【二维差分】2132. 用邮票贴满网格图
本文涉及知识点 二维差分 LeetCode2132. 用邮票贴满网格图 给你一个 m x n 的二进制矩阵 grid ,每个格子要么为 0 (空)要么为 1 (被占据)。 给你邮票的尺寸为 stampHeight x stampWidth 。我们想将邮票贴进二进制矩…...
【前端项目笔记】2 主页布局
主页布局 element-ui提供的组件名称就是它的类名 ☆☆ CSS选择器: (1)基本选择器 类型选择器 p/span/div…… 类选择器 (.classname) ID选择器 (#idname) 通配选择器 ( * ) (2)属性选择器 选择具有特定属性或属性值的…...
t265 jetpack 6 px4 ros2
Ubuntu22.04 realsenseSDK2和ROS2Wrapper安装方法,包含T265版本踩坑问题_ros2 realsense-CSDN博客 210 git clone https://github.com/IntelRealSense/librealsense.git 212 git branch 215 git tag 218 git checkout v2.51.1 219 git branch 265 git clone https://…...
vue 应用测试(一) --- 介绍
vue 应用测试(一) ---介绍 前端测试简介组件测试Jest 测试框架简介其他测试框架 第一个测试避免误报如何组织测试代码 组件挂载Vue2 组件挂载的方式Vue3 的挂载方式vue-test-utils挂载选项 如何调试测试用例参考小结 前端测试简介 软件测试:…...
Perl 语言入门学习
一、介绍 Perl 是一种高级的、动态的、解释型的通用编程语言,由Larry Wall于1987年开发。它是一种非常灵活和强大的语言,广泛用于文本处理、系统管理、网络编程、图形编程等领域。 Perl 语言的设计理念是“用一种简单的语法,去解决复杂的编…...
HarmongOS打包[保姆级]
创建应用 首先进入 华为开发者联盟-HarmonyOS开发者官网 然后进行登录。 登录成功后,鼠标悬停在在登录右上角那个位置后再点击管理中心,进入下面这个界面。 再点击:应用服务–>应用发布–>新建–>完善信息 构建和生成私钥和证书请求…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...
spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
