将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开发者官网 然后进行登录。 登录成功后,鼠标悬停在在登录右上角那个位置后再点击管理中心,进入下面这个界面。 再点击:应用服务–>应用发布–>新建–>完善信息 构建和生成私钥和证书请求…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
