将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
- 里面的
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
是浏览器扩展的背景脚本,负责处理一些全局的后台任务,例如:
- 后台逻辑:处理定时任务、全局事件监听器等。
- 与服务器通信:从服务器获取数据,处理服务器响应。
- 管理浏览器标签页:创建、更新或关闭标签页。
- 在不同页面间传递消息:与内容脚本(如
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开发者官网 然后进行登录。 登录成功后,鼠标悬停在在登录右上角那个位置后再点击管理中心,进入下面这个界面。 再点击:应用服务–>应用发布–>新建–>完善信息 构建和生成私钥和证书请求…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...

通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...