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

时间:2016-10-21 03:09:13

标签: javascript firefox-addon firefox-addon-sdk flowplayer

我正在尝试编写一个供个人使用的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脚本一样运行。所以,我应该能够使用这个功能。那是对的吗?我该如何解决这个问题?

我的油脂脚本

// ==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");
}

我对此很陌生,所以请耐心等待我:)

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

1 个答案:

答案 0 :(得分:1)

您遇到的问题是您没有考虑到您的内容脚本是在与网页(页面脚本)中的脚本不同的上下文中执行的。保持内容脚本与页面脚本分离是浏览器扩展的常规体系结构,这是出于安全原因而完成的。您的内容脚本具有比授予页面脚本更高的权限。虽然从技术上讲,您可以在内容脚本上下文中执行页面提供的功能,但出于安全考虑,您绝不应该这样做。如果您确实选择这样做,则您的扩展程序不会通过Mozilla审核,以便列在AMO上。

虽然您可以expose functions which exist in your content script to page scriptscreate 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事件将start发送到内容脚本。内容脚本仅在附加时加载/执行。因此,通过发送start通知内容脚本它是附加的是多余的。如果您打算将代码修改为仅发送start以响应某些其他事件(例如,用户单击按钮),则这可能是合理的。但是,如果您打算始终自动启动Flowplayer,则无需向内容脚本发送setTimeout消息。内容脚本可以有$(document).ready(function(){ //connect to the socket server. var socket = io.connect('http://' + document.domain + ':' + location.port + '/test'); //receive details from server socket.on('connect', function() { socket.emit('my_event', {data: 'I\'m connected!'}); }); socket.on('new_count', function(msg) { console.log("Received count"); //get data var tags = msg.data; console.log(tags[0].key); numbers_string = ''; for (var i = 0; i < tags.length; i++){ numbers_string = numbers_string + '<p>' + tags[i].key + ': ' + tags[i].value + '</p>'; } $('#vis').html(numbers_string); socket.emit("my_event", {data: "one update received!"}); }); }); ,只需在运行时执行该代码即可。

相关问题