启动 Firefox、使用特权 nsI* API 驱动第 3 方网站的最简单方法

2024-02-14

启动 Firefox 最简单的方法是什么,加载第 3 方网站(我是授权的“自动化”),并针对该站点运行一些“特权”API? (例如:nsIProgressListener、nsIWindowMediator 等)。

我尝试了两种方法:

  1. 使用 XULrunner 创建选项卡式浏览器,“管道”第 3 方站点打开新窗口、遵循 302 重定向等所需的所有适当 API。这样做会产生大量代码,并且需要(据我所知)用户安装应用程序,或使用 -app 运行 Firefox。它也极其脆弱。 :-/

  2. 启动 Firefox,传递第 3 方站点的 URL,MozRepl 已在侦听。然后启动后不久,从“启动”脚本远程登录到 MozRepl,使用 mozIJSSubScriptLoader::loadSubScript 加载我的代码,然后在第 3 方站点的上下文中从 MozRepl 执行我的代码 --这就是我目前正在做的方式.

使用第一种方法,我(显然)遇到了很多安全问题需要解决,而且看起来我编写的浏览器“管道”代码比自动化代码多了 10 倍。

使用第二种方法,我看到很多“计时问题”,即:

  • MozRepl 以某种方式阻止第 3 方站点加载(或执行我提供的特权代码)???,或者
  • 第 3 方网站加载,但 MozRepl 执行的代码看不到它加载,或者
  • 第 3 方网站加载,并且 MozRepl 尚未准备好接受请求(尽管页面中运行其他 JavaScript,并且端口 4242 被 Firefox 进程绑定),
  • etc.

我想也许做这样的事情:

以某种方式修改 MozRepl 源代码,以便在启动时从文件系统中的可预测位置加载特权 JavaScript(或与 Firefox 命令行参数交互),并在第 3 方网站的上下文中执行它。

...或者甚至编写另一个更专注于该任务的类似附加组件。

还有更简单的想法吗?


Update:

经过大量的反复试验,回答了我自己的问题(如下)。


我发现最简单的方法是编写一个专门构建的 Firefox 扩展!

Step 1.我不想做一堆不必要的 XUL/addon 相关的事情; “引导”(或无需重新启动)扩展只需要一个install.rdf文件来识别插件,以及bootstrap.js文件来实现引导接口。

  • 引导扩展:https://developer.mozilla.org/en-US/docs/Extensions/Bootstrapped_extensions https://developer.mozilla.org/en-US/docs/Extensions/Bootstrapped_extensions

  • 好例子:http://blog.fpmurphy.com/2011/02/firefox-4-restartless-add-ons.html http://blog.fpmurphy.com/2011/02/firefox-4-restartless-add-ons.html

bootstrap接口的实现非常简单:

const path = '/PATH/TO/EXTERNAL/CODE.js';
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
var loaderSvc = Cc["@mozilla.org/moz/jssubscript-loader;1"];
                    .getService(Ci.mozIJSSubScriptLoader);

function install() {}
function uninstall() {}
function shutdown(data, reason) {}
function startup(data, reason) { loaderSvc.loadSubScript("file://"+path); }

您可以通过输入来编译扩展install.rdf and bootstrap.js进入新 zip 文件的顶层,并将 zip 文件扩展名重命名为.xpi.

Step 2.为了拥有可重复的生产和测试环境,我发现最简单的方法是使用专用于自动化任务的配置文件启动 Firefox:

  • 启动 Firefox 配置文件管理器:firefox -ProfileManager
  • 创建一个新的配置文件,指定位置以便于重复使用(我将我的配置文件称为testing-profile),然后退出配置文件管理器。
  • 从中删除新的配置文件profiles.ini在您用户的 mozilla 配置中(这样就不会干扰正常浏览)。
  • 使用该配置文件启动 Firefox:firefox -profile /path/to/testing-profile
  • 从文件系统(而不是 addons.mozilla.org)安装扩展。
  • 执行准备配置文件所需的任何其他操作。 (例如:我需要添加第 3 方证书并允许相关域的弹出窗口。)
  • 留个单about:blank打开选项卡,然后退出 Firefox。
  • 快照配置文件:tar cvf testing-profile-snapshot.tar /path/to/testing-profile

从那时起,每次运行自动化时,我都会解压testing-profile-snapshot.tar超过现有的testing-profile文件夹并运行firefox -profile /path/to/testing-profile about:blank使用“原始”配置文件。

Step 3.所以现在当我启动 Firefox 时testing-profile它将“包含”外部代码/PATH/TO/EXTERNAL/CODE.js在每次启动时。

NOTE:我发现我必须移动/PATH/TO/EXTERNAL/步骤期间别处的文件夹2如上所述,因为外部 JavaScript 代码将被缓存(!!!- 在开发过程中不需要)在配置文件内(即:在下次启动时不会看到对外部代码的更改)。

外部代码具有特权,可以使用任何 Mozilla 平台 API。然而,存在一个时机的问题。包含外部代码(并因此执行)的时刻是没有 Chrome 窗口对象(因此没有DOMWindow对象)仍然存在。

所以我们需要等待,直到有一个有用的DOMWindow object:

// useful services.
Cu.import("resource://gre/modules/Services.jsm");    
var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
                .getService(Ci.mozIJSSubScriptLoader);

var wmSvc = Cc["@mozilla.org/appshell/window-mediator;1"]
                .getService(Ci.nsIWindowMediator);

var logSvc = Cc["@mozilla.org/consoleservice;1"]
                .getService(Ci.nsIConsoleService);

// "user" code entry point.
function user_code() {   
   // your code here!
   // window, gBrowser, etc work as per MozRepl!
}

// get the gBrowser, first (about:blank) domWindow, 
// and set up common globals.
var done_startup = 0;
var windowListener;
function do_startup(win) {

    if (done_startup) return;
    done_startup = 1;
    wm.removeListener(windowListener);

    var browserEnum = wm.getEnumerator("navigator:browser");
    var browserWin = browserEnum.getNext();
    var tabbrowser = browserWin.gBrowser;
    var currentBrowser = tabbrowser.getBrowserAtIndex(0);
    var domWindow = currentBrowser.contentWindow;
    window = domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                 .getInterface(Ci.nsIWebNavigation)
                 .QueryInterface(Ci.nsIDocShellTreeItem)
                 .rootTreeItem.QueryInterface(Ci.nsIInterfaceRequestor)
                 .getInterface(Ci.nsIDOMWindow);
    gBrowser = window.gBrowser;

    setTimeout = window.setTimeout;
    setInterval = window.setInterval;
    alert = function(message) { 
        Services.prompt.alert(null, "alert", message); 
    };
    console = { 
        log: function(message) { 
            logSvc.logStringMessage(message); 
        } 
    };

    // the first domWindow will finish loading a little later than gBrowser...
    gBrowser.addEventListener('load', function() {
        gBrowser.removeEventListener('load', arguments.callee, true);
        user_code();
    }, true);
}

// window listener implementation
windowListener = {
    onWindowTitleChange: function(aWindow, aTitle) {},
    onCloseWindow:       function(aWindow) {},
    onOpenWindow:        function(aWindow) {
        var win = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
        win.addEventListener("load", function(aEvent) {
            win.removeEventListener("load", arguments.callee, false);
            if (aEvent.originalTarget.nodeName != "#document") return;
            do_startup();
        }
};

// CODE ENTRY POINT!
wm.addListener(windowListener);

Step 4.所有这些代码都在“全局”范围内执行。如果您稍后需要加载其他 JavaScript 文件(例如:jQuery),请调用loadSubscript明确地在null(全球!)范围

function some_user_code() {
    loader.loadSubScript.call(null,"file:///PATH/TO/SOME/CODE.js");
    loader.loadSubScript.call(null,"http://HOST/PATH/TO/jquery.js");
    $ = jQuery = window.$;
}

现在我们可以使用jQuery on any DOMWindow通过传递<DOMWindow>.document作为选择器调用的第二个参数!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

启动 Firefox、使用特权 nsI* API 驱动第 3 方网站的最简单方法 的相关文章

  • 自动调整Google网站嵌入代码的高度(html)

    我正在使用 Google 协作平台嵌入 HTML 代码 将代码粘贴到 从网络嵌入 窗口中 输出的长度是可变的 我希望有一种方法可以动态调整父级的高度iframeGoogle 协作平台用于托管我的 HTML 我知道我可以使用 Google 协
  • 如何在 Firefox 控制台中访问附加内容脚本?

    我为 Firefox 和 Chrome 开发了一个插件 它有内容脚本 我想在浏览器选项卡的控制台中访问它们 在 Firefox 上网页控制台 https developer mozilla org en US docs Tools Web
  • Jasmine-jQuery loadFixtures 未定义

    我对整个茉莉花的事情仍然很陌生 在过去的几个小时里我陷入了这个问题 我尝试使用 loadFixture 加载外部夹具文件 我使用 Jasmine 2 0 0 和 Jasmine jQuery 2 0 5 ReferenceError loa
  • 通过pm2运行node.js,但经常重新启动:通过信号[SIGINT]以代码[0]退出

    我试图在我的系统上运行 node js 但遇到了这个问题 2016 06 01 20 46 28 App app with id 13 and pid 12633 exited with code 0 via signal SIGINT 2
  • 在 Javascript 中获取第一个数字出现后的子字符串

    我正在尝试提取第一个数字之后 并包括 的字符 ABC 123SD gt 123SD 123 gt 123 123SD gt 123SD ABC gt 我当前的解决方案如下 var string1 ABC 123SD var firstDig
  • Javascript DOM setAttribute 在函数调用中不起作用

    我有一个带有输入元素的 HTML 文件 我希望向其中添加一个名为 valid fieldset011 的新属性 该属性用作 AngularJS 验证器的链接 输入元素具有属性 id fieldset011 如果我使用以下脚本 包含在脚本标签
  • Angular 2 Material 2 日期选择器日期格式

    我不知道如何更改材料2日期选择器的日期格式 我已阅读文档 但我不明白我实际上需要做什么 datepicker默认提供的输出日期格式为f e 6 9 2017 我想要实现的目标是将格式更改为类似的格式9 Jun 2017或任何其他 文档htt
  • Javascript - 在加载所有图像后执行

    看了别人的问题我想 window onload 会回答我的问题 我已经尝试过这个 但它会在页面加载时立即执行代码 而不是在图像加载之后 如果有什么区别的话 图像来自 CDN 并且不是相对的 有人知道解决办法吗 我没有使用 jQuery 想要
  • 打开 md-calendar 时滚动到当前日期

    目前正在构建一个使用 Angular Material 的应用程序 我们需要一个 md calendar 组件 我们想要自定义按钮样式和内容 因此不使用普通的 md datepicker 问题是 当 md calender 打开时 滚动位置
  • 限制可选 DOM 复选框

    我试图限制用户可以选择的复选框数量 这些复选框是为数组中的每个项目生成的 DOM 输入对象 我目前对此没有运气 因此非常感谢任何帮助 谢谢 在这里小提琴 http jsfiddle net vVxM2 222 http jsfiddle n
  • 启用/禁用由用户输入确定的复选框

    我有一个简单的表单 用户可以在其中输入他的联系号码 如果联系号码以 07 开头 则该复选框已启用 其他我需要禁用它的复选框 我已经编写了一些代码 但我面临的问题是 当用户键入 01 时 它会被禁用 但如果他们继续在 01 之后添加任何其他数
  • 确定元素是在页面折叠上方还是下方

    我有一些页面有多个输入框 用户可以在其中输入文本 在单击 下一步 按钮之前 需要填写其中一些内容 我弹出验证错误供用户查看 但是如果问题不在页面上 我希望页面滚动到它 而不是他们必须搜索丢失 错误的字段 我有一个滚动到位 但我无法确定要滚动
  • 更快地开发和测试打印样式表的方法(避免每次都进行打印预览)?

    这是我现在的流程 保存对 print css 的更改 打开浏览器并刷新页面 右键单击并选择 打印 gt 打印预览 Firefox 但实际上是任何浏览器 第三步让我烦恼 我想知道是否可以通过插件或其他东西将其从流程中删除 只需选择以打印媒体形
  • 如何以编程方式退出或关闭 Javascript UWP 应用程序? (Windows 10)

    我制作了一个游戏 它需要自己的退出按钮 我无法使用CoreApplication Exit https msdn microsoft com en us library windows apps windows applicationmod
  • 循环遍历元素并逐步为每个元素应用 CSS 规则

    我有一个网格布局 每个网格布局中都有不同数量的元素 我想动态添加内联grid column通过循环遍历 div 中存在的每个元素的 CSS 规则 ul 与一类 list 所以 HTML 代码的输出需要是 ul class list ul u
  • 在 jQuery 可排序中对多个选定项目进行排序?

    我试图在 jQuery 可排序集中选择多个项目 然后将选定的项目一起移动 这是我的弱点开始尝试使其发挥作用 http jsfiddle net benstenson CgD8Y 这是代码 HTML div class container d
  • 如何更改自动完成中的结果过滤器?

    我不想进行字面匹配 而是想通过正则表达式选择结果 我可以覆盖自动完成的默认行为来完成此任务还是需要替代结构 有一个内置的方法可以做到这一点 只需提供一个函数source http jqueryui com demos autocomplet
  • Google 地图 API:忽略 DirectionService 请求中的季节性限制

    我目前正在开发一张地图 其中显示两点之间的最短路线 使用不同的交通工具 我注意到 有时 例如在冬季关闭的道路不会被考虑在内 我发现我可以使用方向服务 下面的代码 忽略高速公路 收费站和渡轮 但我一生都无法弄清楚如何 是否可以忽略季节性限制
  • 如何处理requireJs超时错误?

    我正在使用 require js 作为加载框架编写一个移动混合应用程序 我遇到加载错误的问题 我想做的是在设备离线且无法下载在屏幕上显示地图所需的 google 地图 API 脚本时设置后备解决方案 我得到的只是 Uncaught Erro
  • 如何使用 jQuery 或 JavaScript 聚焦 或 标签?

    for var i 0 i

随机推荐

  • IE9 现在会支持 WebSocket 吗?

    这个问题很简单 老话题是here https stackoverflow com questions 3377096 will ie9 support webgl and or websockets 自从 IE9 将于 2011 年 3 月
  • Verilog 中的“net”代表什么?

    我刚刚开始学习Verilog 据我了解 Verilog有net数据类型 什么是net代表 网络就是这样一种数据类型 您不使用它来存储值 它们代表物理连接 您可以将线路视为一种网络数据类型 你可以去网上看看更多here http www ee
  • 使用 KernelClient API 在 ipython 内核中执行代码

    我有一个现有的 ipython 内核 带有一个通信文件 path comm file json 我想使用内核客户端 API 执行该内核中的代码 实际上我并不挑剔 任何方法都可以 我明白这是从 jupyter 做事情的最好方法文档 https
  • 从事神经网络项目[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 神经网络是否需要仅采用二进制训练集
  • Trello 如何如此快速地显示历史记录?

    Trello 显示自论坛成立以来任何用户所做的一切的历史日志 同样 如果您单击特定的卡片 它会显示任何人与该卡片相关的任何操作的历史记录 跟踪无限期保留的每个更改 添加 删除必须收集大量数据 并且还可能成为写入历史记录日志的瓶颈 假设它立即
  • 如何在提交之前做一些事情?

    我有一个表单 其中有一个提交表单的按钮 我需要在提交发生之前做一些事情 我尝试做onClick在该按钮上 但它发生在提交之后 我无法共享代码 但一般来说 我应该在 jQuery 或 JS 中做什么来处理这个问题 如果您有这样的表格
  • c - strcmp 对于相等的字符串不返回 0

    因此 我尝试广泛寻找解决方案 但只能真正找到其中一个字符串缺少新行或空字节的帖子 我相当确定这里的情况并非如此 我正在使用以下函数将单词与包含单词列表的文件进行比较 其中每行一个单词 函数中的字典 这是代码 int isWord char
  • 在 DataGridView 的列中搜索值

    我希望用户能够在 DataGridView dgv 的列中搜索数字 dgv 可以保持许多记录 每条记录都有一个项目编号 因此 我希望用户能够在 项目编号 列中搜索项目编号 我的列是 ProjectID 不可见 图片 无标题文本 项目编号 项
  • 如何在标准输出中禁用 spring boot 徽标?

    有没有办法禁用可爱但非常明显的 ASCII Spring boot 徽标 Spring Boot v1 1 8 RELEASE 每次运行 Spring Boot 应用程序时都会
  • MySQL中使用clearDB自动加1

    我正在使用带有clearDB 的Windows Azure 当前数据库自增值为10 我希望它为1 我尝试在 PHPMyAdmin 中运行这些命令 1 set global auto increment increment 1 set glo
  • 在 Thread + Queue 或 ThreadPoolExecutor 上使用 async-await?

    我从未使用过async await语法 但我经常需要发出 HTTP S 请求并解析响应 同时等待未来的响应 为了完成这项任务 我目前使用线程池执行器 https docs python org 3 library concurrent fu
  • 从另一个类调用委托方法

    我无法弄清楚如何在 C 中对跨类的委托方法调用进行编程 我来自 Objective C 的世界 这可能会让我感到困惑 在 Objective C 中 我可以在子类中分配一个委托对象作为父类 即 childViewcontroller del
  • 自定义 asp.net 身份存储 - 为什么 HttpContext.Current 有时为空

    我按照示例集实现了 ASP NET Identity 的自定义用户存储here http www jamessturtevant com posts ASPNET Identity2 0 Custom Database 一切正常 除了这个
  • 扩展应用程序还是使用单例?

    我有一个 android 项目 其中有一个或多个活动需要访问的不同对象 现在我正在考虑创建一个子类Application然而根据文档 http developer android com reference android app Appl
  • 通过单元格的值动态设置 Excel 图表数据系列范围

    我在 Excel 中有一个简单的图表 其中绘制了 2 个数据系列 引用了第 3 个数据系列 我想要做的是根据单元格中的数字更改第一个数据系列之一的范围 例如 如果数字为 1 并且数据系列位于 A 列中 则图表的范围应为A1 A100 现在
  • 在 Yii2 中一次保存多个模型

    我有两个模型 Users and Students 我想同时将数据插入到这些表中 首先 我将数据保存到Students模型 然后进入Users楷模 现在 如果数据没有成功插入到Users模型已经有一个条目Students桌子 我想要的是仅当
  • Akka Actor 带有 TimeoutException 的“询问”和“等待”

    我正在使用 Scala 和 Akka 建模一个简单的 P2P class Node extends Peer with Actor var peers List ActorRef List def receive case register
  • iOS13 getUserMedia 不适用于 Chrome 和 Edge

    我和我的朋友正在构建一个需要相机访问权限的应用程序 但我们在让相机与 iOS 配合使用时遇到了一些问题 我们使用的是 iOS13 Safari 在获取相机内容后立即冻结 chrome 和 Edge 根本无法获取相机访问权限 我们的代码如下
  • Asp.Net MVC 中 DataAnnotations StringLength 文本框的 maxlength 属性

    我正在开发 MVC2 应用程序 想要设置文本输入的 maxlength 属性 我已经使用数据注释在模型对象上定义了 stringlength 属性 并且它正在正确验证输入字符串的长度 当模型已有信息时 我不想通过手动设置最大长度属性来在视图
  • 启动 Firefox、使用特权 nsI* API 驱动第 3 方网站的最简单方法

    启动 Firefox 最简单的方法是什么 加载第 3 方网站 我是授权的 自动化 并针对该站点运行一些 特权 API 例如 nsIProgressListener nsIWindowMediator 等 我尝试了两种方法 使用 XULrun