如何在内容脚本中使用Flowplayer功能?

Yas*_*oft 8 javascript firefox-addon flowplayer firefox-addon-sdk

我正在尝试编写一个Firefox附加组件供个人使用,并学习更多关于JavaScript和Firefox附加组件的SDK.加载项应该打开一个vivo.sxURL,然后自动启动播放器,但我有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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

内容脚本

self.port.on("start", function(a) {
    console.log("Load");
    flowplayer().load();         //ReferenceError: flowplayer is not defined
    console.log("Loaded");
});
Run Code Online (Sandbox Code Playgroud)

第一个问题是函数play触发2次,但应该只运行一次.可能是onAttach因为它无法正常工作.你觉得怎么样?

更重要的问题是ReferenceError.我有一个Greasemonkey脚本,我使用该函数flowplayer().load();.我认为内容脚本像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");
}
Run Code Online (Sandbox Code Playgroud)

我是新手,所以请耐心等待我:)

如果您需要更多信息,请发表评论.

Mak*_*yen 1

您遇到的问题是您没有考虑到您的内容脚本是在与网页中的脚本(页面脚本)不同的上下文中执行的。将内容脚本与页面脚本分开是浏览器扩展的正常架构,这是出于安全原因而这样做的。您的内容脚本具有比授予页面脚本更高的权限。虽然从技术上讲,您可以在内容脚本上下文中执行页面提供的功能,但出于安全原因,您永远不应该这样做。如果您选择这样做,您的扩展程序将不会通过 Mozilla 的审核而无法在AMO上列出。

虽然您可以将内容脚本中存在的函数公开给页面脚本,并在页面脚本范围内创建对象,但是从页面脚本上下文中实际执行代码的方法是将一个<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);
});
Run Code Online (Sandbox Code Playgroud)

onAttach/play运行多次:
如果没有完整的代码和浏览器的屏幕截图,就不可能确定为什么会发生这种情况。

最可能的原因是您打开了多个与 匹配的地址的选项卡"https://vivo.sx/*"onAttach每次将内容脚本附加到页面时都会调用您的代码。对于打开匹配 URL 的每个选项卡,它将附加一次。如果加载附加组件时打开了两个匹配 URL 的选项卡,则代码onAttach将执行两次。

另一种可能性是您执行了vivoplay多次,导致设置了多个PageMods,每个 s 都会将内容脚本的单独副本附加到每个选项卡。鉴于您为此函数使用的名称vivoplay,您可能会将其视为您多次执行的播放函数。根据您在该功能内组织事物的方式,您不应该这样做。

对于所显示的内容来说过于复杂:
对于所显示的内容来说,您的代码过于复杂。您正在使用onAttach事件发送start到内容脚本。内容脚本仅在附加时才加载/执行。因此,通知内容脚本通过发送附加它start是多余的。如果您打算修改代码以仅start响应某些其他事件(例如用户单击按钮)而发送,这可能是合理的。但是,如果您希望始终自动启动 Flowplayer,则无需start向内容脚本发送消息。内容脚本可以具有setTimeout,并且在运行时继续执行该代码。