Firefox WebExtention无法加载

时间:2016-07-15 02:15:55

标签: firefox-addon firefox-webextensions

所以,我尝试使用Firefox中的about:debugging页面加载我的插件。但是,它根本不会加载。是否存在可以记录错误的地方?

这是我的 manifest.JSON 代码:

{
    "description": "Adds a stickfigure",
    "manifest_version": 2,
    "name": "StickMan",
    "version": "1.0",
    "icons": {
        "48": "icons/StickMan-48.png"
    },
    "applications": {
        "gecko": {
          "id": "extention@stick.man",
          "strict_min_version": "45.0"
        }
    },
    "permissions": [
        "activeTab"
    ],
    "background": {
        "scripts": ["StickManUpdate.js"]
    },
    "browser_action": {
        "default_icon": {
            "48": "icons/StickManButton.png"
        },
        "default_title": "Call StickMan",
    },
}

我希望这有助于其他受挫的附加创作者。

提前致谢

1 个答案:

答案 0 :(得分:1)

缺少加载问题是您的 manifest.json 文件的JSON中存在多个语法错误。在 manifest.json 文件中,文件末尾的行:

        "default_title": "Call StickMan",
    },
}

不应该有额外的,(这表明你将在Object中拥有另一个属性):

        "default_title": "Call StickMan"
    }
}

如果您使用的是Firefox Developer Edition,那么您遇到这些错误的事实就很明显了:

FF dev edition WebExtension load error

但是,即使您运行的是Firefox 47.0.1并且只使用了Browser Console(键盘快捷键: Ctrl - Shift - J ),如suggested in the comments,你会看到错误:

A promise chain failed to handle a rejection. Did you forget to '.catch', or did you forget to 'return'?
See https://developer.mozilla.org/Mozilla/JavaScript_code_modules/Promise.jsm/Promise

Date: Sun Jul 17 2016 11:11:22 GMT-0700 (Pacific Standard Time)
Full Message: SyntaxError: JSON.parse: expected double-quoted property name at line 33 column 2 of the JSON data
Full Stack: readJSON/</<@resource://gre/modules/Extension.jsm:628:19
NetUtil_asyncFetch/<.onStopRequest@resource://gre/modules/NetUtil.jsm:128:17

虽然有点神秘,但仍显示第一期的行号:

Full Message: SyntaxError: JSON.parse: expected double-quoted property name at line 33 column 2 of the JSON data

Firefox Developer Edition的浏览器控制台中产生的错误更容易解析问题所在:

SyntaxError: JSON.parse: expected double-quoted property name at line 33 column 2 of the JSON data
Stack trace:
readJSON/</<@resource://gre/modules/Extension.jsm:859:19
NetUtil_asyncFetch/<.onStopRequest@resource://gre/modules/NetUtil.jsm:128:17

WebExtensions开发:
WebExtensions API目前正在开发中。如果您正在开发WebExtension,您应该使用Firefox NightlyFirefox Developer Edition来测试代码

有关您的代码的更多内容:

语法错误:
除了上述语法错误之外,还有更多问题。我没有尝试解决所有这些问题,但确实已经陷入了足够的修复,以便附加功能正常运行。下一个报告的错误(语法错误)位于代码中的 StickManUpdate.js 文件中:

browser.tabs.sendMessage(
    message: "End";
);

这里有多个问题。请参阅tabs.sendMessage() documentation。您缺少必需的tabId参数。此外,您似乎混淆了将Object作为参数传递的区别,该参数包含作为传递给方法的信息的属性与传递给方法的其他本机类型的参数列表。注意:同时存在各种本机或非本机类型的参数列表以及包含传递给该方法的数据的属性的对象并不罕见。

假设browserAction已定义:
您可以在browserAction的多个位置使用browser.browserAction的方法。 browserAction本身没有定义。或者,您可以使用browserAction作为快捷方式,将其定义为:var browserAction = browser.browserAction;

使用browserAction.getTitle()就像它是同步的,但实际上它是异步的:
您拨打browserAction.getTitle()来获取标题的值。标题的值仅在您不提供的回调函数中可用。这意味着缺乏对异步编程的理解。您可能希望查看有关该主题的一些问题,如:

提供给browserAction.setTitle()的参数类型错误:
这似乎又混淆了其他本机类型的参数与作为Object(可能是Object literal)的参数之间的差异,该参数包含作为传递给该方法的信息的属性。不可否认,在将信息传递给方法时,WebExtensions似乎几乎任意混合使用实际参数和具有作为参数的属性的对象。似乎需要注意在特定方法中使用哪种方法。

没有各种功能指定标签的ID:
在对各种方法的多次调用中,您不应该在应该的时候传递tabId。您只需点击鼠标即可将StickMan canvas添加到单个标签中。您应该传递选项卡ID以调用多个方法。

分配到 stickman.js中的document.body.innerHTML
通常,如果可能,应该避免在任何时候分配给innerHTML。在大多数情况下,这是一个坏主意。在大多数情况下,它可能会导致重新评估整个DOM。为了做你想做的事情,在文本格式中将HTML添加到元素的HTML末尾的DOM中,有一个更好/更快的特定函数:insertAdjacentHTML()。你的代码:

document.body.innerHTML+= '<canvas id="StickManCanvas0000000" width="100" height="200"></canvas>';

可以写成:

document.body.insertAdjacentHTML("beforeend", '<canvas id="StickManCanvas0000000" width="100" height="200"></canvas>');

但是,在这里使用insertAdjacentHTML()仍然是一个坏主意。使用insertAdjacentHTML()或分配给innerHTML会产生严重的耻辱感。使用其中任何一个都会导致您的加载项在提交给AMO进行分发时会受到额外的审查。这主要是因为使用这两种方法来改变DOM存在真正的安全问题。安全问题是指添加的内容是从输入/数据动态生成的文本,这些文本未硬编码到附加组件中。此外,您已经混合将元素添加为文本并使用其他JavaScript对其执行更改(例如,分配给canvas.style.position)。你真的应该使用其中一个。在这种情况下,最好在JavaScript中完全构造canvas。毕竟,只有4行才能执行您在innerHTML作业中使用的两行以及getElementById()找到canvas元素时所执行的操作。

就个人而言,我喜欢在许多具有复杂结构的实例中使用insertAdjacentHTML()。使用它来插入大量HTML通常会更快。它还允许您保持插入的内容表示为文本。这样的文本可能很多更容易可视化添加的结构,而不是弄清楚使用document.createElement()setAttribute()生成的大块DOM实际上是什么样的。但是,除了上面提到的其他缺点之外,使用insertAdjacentHTML()可能不会轻易编写模块化代码。

关于如何插入内容脚本和canvas的问题: 每次用户单击您的browserAction按钮时,您都会将另一个内容脚本副本插入到选项卡中。这会导致由于消费的内容脚本收到您通过browser.tabs.sendMessage()调用发送的消息而无法找到canvas而导致出现错误的问题。对此的正确解决方案是,第一次在选项卡中单击按钮时仅chrome.tabs.executeScript(),然后在该选项卡中单击按钮后每次向内容脚本发送一条消息,从而导致相同的canvas要重新插入DOM。跟踪您是否已将StickMan加载到特定选项卡的简单方法是使用setTitle()使该按钮的标题在该选项卡中首次运行后不同。

其他问题:
注意: stickman.js 中的代码结构有点复杂。你可能想解决这个问题。

一起

的manifest.json

{
    "description": "Adds a stickfigure",
    "manifest_version": 2,
    "name": "StickMan",
    "version": "1.0",
    "icons": {
        "48": "icons/StickMan-48.png"
    },
    "applications": {
        "gecko": {
            "id": "extention@stick.man",
            "strict_min_version": "45.0"
        }
    },
    "permissions": [
        "activeTab"
    ],
    "background": {
        "scripts": ["StickManUpdate.js"]
    },
    "browser_action": {
        "default_icon": {
            "48": "icons/StickManButton.png"
        },
        "default_title": "Call StickMan",
        "browser_style": true
    }
}

StickManUpdate.js

browser.browserAction.onClicked.addListener(function(tab) {
    browser.browserAction.getTitle({tabId:tab.id},function(title){
        if(title  === 'Call StickMan') {
            chrome.tabs.executeScript(tab.id, {
                file: "/content_scripts/stickman.js"
            });
            browser.browserAction.setTitle({title:'Recall StickMan',tabId:tab.id});
        } else if (title  === 'Call StickMan again') {
            browser.tabs.sendMessage(tab.id,"Draw");
            browser.browserAction.setTitle({title:'Recall StickMan',tabId:tab.id});
        }else {
            browser.tabs.sendMessage(tab.id,"End");
            browser.browserAction.setTitle({title:'Call StickMan again',tabId:tab.id});
        }
    });
});

stickman.js

var running = true;
//document.body.insertAdjacentHTML("beforeend", '<canvas id="StickManCanvas0000000" width="100" height="200"></canvas>');
var canvas = document.createElement("canvas");
canvas.setAttribute("width",100);
canvas.setAttribute("height",200);
//var canvas = document.getElementById('StickManCanvas0000000');
canvas.style.position = 'fixed';
canvas.style.left = '0px';
canvas.style.top = (window.innerHeight-200)+'px';
canvas.style.backgroundColor = 'rgba(0, 0, 0, 0)';
canvas.style.border = '1px dashed red';

var ctx = canvas.getContext('2d');

var pos = {
    x:0,
    headX:50,
    headY:20,
    bodyX:50,
    bodyY:150,
    leftArmX:25,
    leftArmY:90,
    rightArmX:75,
    rightArmY:90,
    leftLegX:30,
    leftLegY:200,
    rightLegX:70,
    rightLegY:200,
};

var setPos = function(x, y) {
    canvas.style.left = x+'px';
    canvas.style.top = (window.innerHeight-y-200)+'px';
};

var drawMan = function(time) {
    setPos(pos.x, 0);
    ctx.strokeStyle = '#000000';
    ctx.lineWidth = 5;
    ctx.beginPath();
    ctx.arc(pos.headX, pos.headY, 20, 0, Math.PI*2, false);
    ctx.moveTo(pos.headX, pos.headY);
    ctx.lineTo(pos.bodyX, pos.bodyY);
    ctx.lineTo(pos.rightLegX, pos.rightLegY);
    ctx.moveTo(pos.bodyX, pos.bodyY);
    ctx.lineTo(pos.leftLegX, pos.leftLegY);
    ctx.moveTo((pos.bodyX+pos.headX)/2, ((pos.bodyY+pos.headY)/5)*2);
    ctx.lineTo(pos.rightArmX, pos.rightArmY);
    ctx.moveTo((pos.bodyX+pos.headX)/2, ((pos.bodyY+pos.headY)/5)*2);
    ctx.lineTo(pos.leftArmX, pos.leftArmY);
    ctx.stroke();
    ctx.fillStyle = '#888888';
    ctx.beginPath();
    ctx.arc(pos.headX, pos.headY, 20, 0, Math.PI*2, false);
    ctx.fill();
    if(running) {
        window.requestAnimationFrame(drawMan);
    }
};

drawMan();
document.body.appendChild(canvas);

browser.runtime.onMessage.addListener(function(m) {
    if(m === 'End' && running === true) {
        running = false;
        document.body.removeChild(canvas);
    } else if(m === 'Draw' && running === false) {
        running = true;
        document.body.appendChild(canvas);
    }
});

功能演示[注1:You must navigate to an actual webpage。注意2:弹出的工具提示告诉您browser_action按钮的标题不会被program I used捕获,以创建以下 .gif 。注3:我将browser_style属性添加到 manifest.json 文件中的browser_action。它是Firefox 48中的新功能。没有它,Firefox将在加载加载项时在浏览器控制台中发出警告。]:

StickMan Functionality demo