如何在内容脚本中使用 Flowplayer 函数?
How to use Flowplayer functions in a content script?
我正在尝试编写一个供个人使用的 Firefox 附加组件,并想进一步了解 JavaScript 和 Firefox 附加组件 SDK。加载项应该打开 vivo.sx
URL 然后自动启动播放器,但我有 2 个问题。希望大家帮帮我。
相关插件代码:
function vivoplay()
{
pageMod.PageMod({
include: "https://vivo.sx/*",
contentScriptFile: "./vivoplay.js",
onAttach: play
});
function play(worker) //Fires 2 Times
{
console.log("Timeout");
tmr.setTimeout(sendplay, 14000);
function sendplay()
{
var a = 0;
worker.port.emit("start", a);
}
}
}
内容脚本
self.port.on("start", function(a) {
console.log("Load");
flowplayer().load(); //ReferenceError: flowplayer is not defined
console.log("Loaded");
});
第一个问题是函数 play
触发了 2 次,但应该只 运行 一次。可能是 onAttach
没有正常工作。你怎么看?
更重要的问题是ReferenceError
。我有一个 Greasemonkey 脚本,我在其中使用函数 flowplayer().load();
。我认为内容脚本像 Greasemonkey 脚本一样 运行ning。所以,我应该可以使用这个功能。那是对的吗?我该如何解决这个问题?
我的 greasemonkey 脚本
// ==UserScript==
// @name 3. Vivo
// @namespace Autoplay
// @include https://vivo.sx/*
// @version 1
// @grant none
// ==/UserScript==
window.setTimeout(Play, 2000);
function Play()
{
flowplayer().load();
console.log("Loaded");
flowplayer().fullscreen();
console.log("Fullscreen started");
}
我对此很陌生,请耐心等待:)
如果您需要更多信息,请发表评论。
您遇到的问题是您没有考虑到您的内容脚本是在与网页脚本(页面脚本)不同的上下文中执行的。出于安全原因,将内容脚本与页面脚本分开是浏览器扩展的正常架构。您的内容脚本具有比授予页面脚本更高的权限。虽然从技术上讲,您可以在内容脚本上下文中执行页面提供的功能,但出于安全原因,您永远不应该这样做。如果您确实选择这样做,您的扩展将不会通过 Mozilla 的审查,因为它被列在 AMO.
虽然您可以 expose functions which exist in your content script to page scripts, and create objects in the page script scope,但从页面脚本上下文中实际执行代码的方法是将 <script>
元素添加到包含您希望执行的代码的 document
.
对于你问题中的代码,这可以实现为:
self.port.on("start", function(a) {
let newScript = document.createElement('script');
//The calls to console.log don't need to be in the page script.
// However, the code in the newScript is executed asynchronously. Thus, if the
// console.log("Loaded");
// is in the content script it will be executed prior to flowplayer().load() actually
// being called.
newScript.innerHTML = 'console.log("Load");'
+ 'flowplayer().load();'
+ 'console.log("Loaded");' ;
document.head.appendChild(newScript);
});
onAttach
/play
运行不止一次:
如果没有您的完整代码和浏览器外观的屏幕截图,则无法确定为什么会发生这种情况。
最可能的原因是您有多个选项卡打开了匹配 "https://vivo.sx/*"
的地址。每次将内容脚本附加到页面时,都会调用您的 onAttach
代码。它将为每个打开匹配 URL 的选项卡附加一次。如果在加载加载项时打开了两个匹配 URL 的选项卡,那么 onAttach
代码将被执行两次。
另一种可能性是您多次执行 vivoplay
导致设置多个 PageMod
,每个都会将您的内容脚本的单独副本附加到每个选项卡。鉴于您为此函数使用的名称 vivoplay
,您可能将其视为您不止一次执行的播放函数。根据您在该功能中组织事物的方式,您不应该这样做。
显示的内容过于复杂:
您的代码对于显示的内容过于复杂。您正在使用 onAttach
事件将 start
发送到内容脚本。附加的内容脚本只有loaded/executed。因此,通过发送 start
通知内容脚本它已附加是多余的。如果您打算将代码修改为仅发送 start
以响应某些其他事件(例如,用户单击按钮),这可能是合理的。但是,如果您打算始终自动启动 Flowplayer,则无需向内容脚本发送 start
消息。内容脚本可以有 setTimeout
并在 运行.
时继续执行该代码
我正在尝试编写一个供个人使用的 Firefox 附加组件,并想进一步了解 JavaScript 和 Firefox 附加组件 SDK。加载项应该打开 vivo.sx
URL 然后自动启动播放器,但我有 2 个问题。希望大家帮帮我。
相关插件代码:
function vivoplay()
{
pageMod.PageMod({
include: "https://vivo.sx/*",
contentScriptFile: "./vivoplay.js",
onAttach: play
});
function play(worker) //Fires 2 Times
{
console.log("Timeout");
tmr.setTimeout(sendplay, 14000);
function sendplay()
{
var a = 0;
worker.port.emit("start", a);
}
}
}
内容脚本
self.port.on("start", function(a) {
console.log("Load");
flowplayer().load(); //ReferenceError: flowplayer is not defined
console.log("Loaded");
});
第一个问题是函数 play
触发了 2 次,但应该只 运行 一次。可能是 onAttach
没有正常工作。你怎么看?
更重要的问题是ReferenceError
。我有一个 Greasemonkey 脚本,我在其中使用函数 flowplayer().load();
。我认为内容脚本像 Greasemonkey 脚本一样 运行ning。所以,我应该可以使用这个功能。那是对的吗?我该如何解决这个问题?
我的 greasemonkey 脚本
// ==UserScript==
// @name 3. Vivo
// @namespace Autoplay
// @include https://vivo.sx/*
// @version 1
// @grant none
// ==/UserScript==
window.setTimeout(Play, 2000);
function Play()
{
flowplayer().load();
console.log("Loaded");
flowplayer().fullscreen();
console.log("Fullscreen started");
}
我对此很陌生,请耐心等待:)
如果您需要更多信息,请发表评论。
您遇到的问题是您没有考虑到您的内容脚本是在与网页脚本(页面脚本)不同的上下文中执行的。出于安全原因,将内容脚本与页面脚本分开是浏览器扩展的正常架构。您的内容脚本具有比授予页面脚本更高的权限。虽然从技术上讲,您可以在内容脚本上下文中执行页面提供的功能,但出于安全原因,您永远不应该这样做。如果您确实选择这样做,您的扩展将不会通过 Mozilla 的审查,因为它被列在 AMO.
虽然您可以 expose functions which exist in your content script to page scripts, and create objects in the page script scope,但从页面脚本上下文中实际执行代码的方法是将 <script>
元素添加到包含您希望执行的代码的 document
.
对于你问题中的代码,这可以实现为:
self.port.on("start", function(a) {
let newScript = document.createElement('script');
//The calls to console.log don't need to be in the page script.
// However, the code in the newScript is executed asynchronously. Thus, if the
// console.log("Loaded");
// is in the content script it will be executed prior to flowplayer().load() actually
// being called.
newScript.innerHTML = 'console.log("Load");'
+ 'flowplayer().load();'
+ 'console.log("Loaded");' ;
document.head.appendChild(newScript);
});
onAttach
/play
运行不止一次:
如果没有您的完整代码和浏览器外观的屏幕截图,则无法确定为什么会发生这种情况。
最可能的原因是您有多个选项卡打开了匹配 "https://vivo.sx/*"
的地址。每次将内容脚本附加到页面时,都会调用您的 onAttach
代码。它将为每个打开匹配 URL 的选项卡附加一次。如果在加载加载项时打开了两个匹配 URL 的选项卡,那么 onAttach
代码将被执行两次。
另一种可能性是您多次执行 vivoplay
导致设置多个 PageMod
,每个都会将您的内容脚本的单独副本附加到每个选项卡。鉴于您为此函数使用的名称 vivoplay
,您可能将其视为您不止一次执行的播放函数。根据您在该功能中组织事物的方式,您不应该这样做。
显示的内容过于复杂:
您的代码对于显示的内容过于复杂。您正在使用 onAttach
事件将 start
发送到内容脚本。附加的内容脚本只有loaded/executed。因此,通过发送 start
通知内容脚本它已附加是多余的。如果您打算将代码修改为仅发送 start
以响应某些其他事件(例如,用户单击按钮),这可能是合理的。但是,如果您打算始终自动启动 Flowplayer,则无需向内容脚本发送 start
消息。内容脚本可以有 setTimeout
并在 运行.