我正在开发谷歌浏览器扩展程序,我正在尝试将与扩展程序捆绑在一起的图像加载到画布中。
var canvas = document.createElement('canvas');
canvas.width = 470;
canvas.height = 470;
var context = canvas.getContext('2d');
var image = new Image();
image.addEventListener('load', function(){
//process
});
image.src = chrome.extension.getURL("asset/gotcha.png");
当我在内容脚本中执行代码时,我得到:
Unable to get image data from canvas because the canvas has been tainted by
cross-origin data.
有没有办法避免这种情况?我已经成功地将图像,音频,视频和Flash直接嵌入到目标站点中,而不会出现任何这些问题。资源列在清单文件中的web_accessible_resources下。
基于ExpertSystem的方法,我得到了一个简单的解决方案。
后台页面的 JavaScript 的第一部分,可以在其中创建画布而不会引发安全异常。
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.message == "convert_image_url_to_data_url") {
var canvas = document.createElement("canvas");
var img = new Image();
img.addEventListener("load", function() {
canvas.getContext("2d").drawImage(img, 0, 0);
sendResponse({data: canvas.toDataURL()});
});
img.src = request.url;
return true; // Required for async sendResponse()
}
}
)
内容脚本的第二部分:
//@success is the callback
function local_url_to_data_url(url, success) {
chrome.runtime.sendMessage(
{message: "convert_image_url_to_data_url", url: url},
function(response) {success(response.data)}
);
}
不能将图像从扩展直接传递到网页的画布而不使其受到污染。
这是一个解决方法:
描述:
- 您可以从背景页面(或内容脚本)访问图像。
- 您将其放在画布中并将其转换为数据URL。
- 您将一些JS代码注入网页,将dataURL作为字符串传递。
- 注入的代码使用字符串 (dataURL) 创建图像(在网页上下文中)并将其绘制到画布上。
示例代码:
/* In `background.js` */
function injectImg(tabID, remoteCanvasID, imgPath) {
var canvas = document.createElement("canvas");
var img = new Image();
img.addEventListener("load", function() {
canvas.getContext("2d").drawImage(img, 0, 0);
var dataURL = canvas.toDataURL();
var code = [
"(function() {",
" var canvas = document.getElementById("" + remoteCanvasID + "");",
" var img = new Image();",
" img.addEventListener("load", function() {",
" canvas.getContext("2d").drawImage(img, 0, 0);",
" });",
" img.src = "" + dataURL + "";",
" ",
"})();"].join("n");
chrome.tabs.executeScript(tabID, { code: code });
});
img.src = chrome.extension.getURL(imgPath);
}
chrome.runtime.onMessage.addListener(function(msg, sender)) {
if (msg.action && (msg.action == "getImg")
&& msg.imgPath && msg.canvasID) {
injectImg(sender.tab.id, msg.canvasID, msg.imgPath);
}
});
/* In `content.js` */
chrome.runtime.sendMessage({
action: "getImg",
imgPath: "some/image.png",
canvasID: "someCanvasID"
});
这是一种更通用的方法(任何具有最低配置的内容脚本都可以使用),但将部分逻辑移动到内容脚本可能更简单。 例如:
- 在内容脚本中定义一个函数,当使用 dataURL 调用该函数时,该函数创建图像并将其绘制到画布上。
- 在后台页面中定义一个函数,该函数采用图像路径并返回数据URL(如上所示)。
- 使用 chrome.runtime.getBackgroundPage() 获取对背景页
window
对象的引用,调用函数将图像路径转换为 dataURL,最后使用该 dataURL 创建图像并将其绘制到画布上。
尝试将资产添加到清单文件顶层的 web_accessible_resources
属性中,例如
"web_accessible_resources": ["asset/gotcha.png"],
如果您还没有这样做。