我正在使用Google Chrome扩展程序与Gmail聊天进行交互,并且可以向所有打开的聊天发送相同的消息,功能部分已完成,但我无法将keydown
事件发送到textareas。< / p>
我正在做的是使用page_action
在用户访问Gmail时显示扩展程序图标。当用户单击扩展图标时,它将提示弹出文本区域,当用户打开聊天并向textarea写入内容然后按 Enter 键,每个打开的聊天的文本区域将填写相同的消息,并支持解雇keydown
事件。
以下是esencial代码:
popup.js
chrome.tabs.executeScript(null, {file: 'send.js'}, function () {
// 'message' is the textarea inside the popup.html
var message = document.getElementById('message');
message.onkeydown = function (e) {
if (13 == e.keyCode) {
chrome.tabs.executeScript(null, {code: 'send("' + message.value + '");'}, function () {
message.value = '';
});
return false;
}
};
});
send.js
function send(message) {
if (message) {
for (var i = 0, textareas = document.getElementsByTagName("TEXTAREA"), length = textareas.length; i < length; ++i) {
textarea = textareas[i];
textarea.value = message;
var evt = document.createEvent('KeyboardEvent');
evt.initKeyboardEvent('keydown', true, true, null, false, false, false, false, 13, 13);
Object.defineProperty(evt, 'keyCode', {
get : function() {
return 13;
}
});
Object.defineProperty(evt, 'which', {
get : function() {
return 13;
}
});
Object.defineProperty(evt, 'keyIdentifier', {
get : function() {
return 'Enter';
}
});
Object.defineProperty(evt, 'shiftKey', {
get : function() {
return false;
}
});
textarea.dispatchEvent(evt);
}
}
}
代码填充textareas时没有问题,因此所有textareas都被重新调整,但是在脚本填充textareas之后keydown
事件没有触发。奇怪的是,当我将 send.js 代码尝试进入谷歌Chrome控制台时,keydown
事件正常启动并且消息被发送,但是我无法做同样的事情。扩展
那么,我怎样才能将keydown
事件发送到扩展名?
答案 0 :(得分:1)
Gmail由框架组成
默认情况下,chrome.tabs.executeScript
仅在主(顶部窗口)框架中注入代码。要在子帧中注入代码,请在您的详细信息中添加allFrames: true
。
此外, NOT 使用'send("' + USER_INPUT_HERE + '");'
来触发您的功能。这使您的应用程序容易受到脚本注入攻击。使用JSON.stringify(USER_INPUT_HERE)
正确转义字符串。
chrome.tabs.executeScript(null, {
file: 'send.js',
allFrames: true
}, function () {
chrome.tabs.executeScript(null, {
code: 'send(' + JSON.stringify(message.value) + ');',
allFrames: true
});
message.value = '';
});
漏洞示例:
用户输入:" + (function(){while(1)chrome.tabs.create({url:"http://evil.com"})}()) + "
子>
扩展程序创建的对象永远不会传递给页面。添加到事件的属性和属性描述符在传递到页面时会丢失。我建议使用injected script What is the difference between an injected script, Content script and extension code? 取代内容脚本,以获得预期效果:
// Script to be injected
var code = '(' + function(message) {
/* .. "function send"'s body from send.js .. */
} + ')(' + JSON.stringify(message.value) + ');';
// Content script which *injects* the script
chrome.tabs.executeScript(null, {
code: 'var s = document.createElement("script");' +
's.textContent = ' + JSON.stringify(code) + ';' +
'(document.head||document.documentElement).appendChild(s);' +
's.parentNode.removeChild(s);' /*<--Clean-up*/
});
为了便于说明,上一个代码段会在页面中生成以下代码injected:
(function(message) { /* logic of send */ })("user input");
在Gmail的页面中构建并传递Event对象,以便保留所有属性,就像您使用控制台执行脚本一样。 不再在您的扩展程序的上下文中运行。