Google Chrome扩展程序中的Fire Keydown事件

时间:2012-06-23 18:55:07

标签: javascript javascript-events google-chrome-extension keydown

我正在使用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事件发送到扩展名?

1 个答案:

答案 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对象,以便保留所有属性,就像您使用控制台执行脚本一样。 不再在您的扩展程序的上下文中运行