简体   繁体   English

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

[英]Fire Keydown event in Google Chrome extension

I'm doing a Google Chrome extension that interacts with Gmail chat and can send the same message to all open chat, the functional part is done, but I can not send the keydown event to the textareas.我正在做一个与 Gmail 聊天交互的 Google Chrome 扩展,可以向所有打开的聊天发送相同的消息,功能部分已完成,但我无法将keydown事件发送到文本区域。

What I am doing is using a page_action to show the extension icon when the user visit Gmail.我正在做的是在用户访问 Gmail 时使用page_action来显示扩展图标。 When the user click the extension icon, it is going to prompt a popup with a textarea, when the user have opened chat and write something to the textarea and then press Enter key, the textarea of each opened chat are going to fill the same message and suppused to fire keydown event.当用户点击扩展图标时,它会提示一个带有文本区域的弹出窗口,当用户打开聊天并向文本区域写入内容然后按回车键时,每个打开的聊天的文本区域将填充相同的消息并应该触发keydown事件。

Here is the essential code:这是基本代码:

popup.js弹窗.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发送.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);
    }
  }
}

The code did not have problem filling the textareas, so all textareas is reconized, but the keydown event did not fire after the script filled textareas.代码在填充文本区域时没有问题,所以所有文本区域都被重新识别,但是在脚本填充文本区域后keydown事件没有触发。 The strange part, is when I tried the send.js code into the Google Chrome console, the keydown event fire normally and the messages were send, but I can't do samething with the extension.奇怪的是,当我尝试将send.js代码放入 Google Chrome 控制台时, keydown事件正常触发并且消息已发送,但我无法对扩展执行相同的操作。

So, how can I fire the keydown event into the extension?那么,如何将keydown事件触发到扩展中呢?

Gmail is composed of frames. Gmail 由框架组成。
By default, chrome.tabs.executeScript only injects code in the main (top-window) frame.默认情况下, chrome.tabs.executeScript仅在主(顶部窗口)框架中注入代码。 To also inject the code in the subframes, add allFrames: true to your details.要同时在子帧中注入代码,请将allFrames: true添加到您的详细信息中。

Also, do NOT use 'send("' + USER_INPUT_HERE + '");'此外,请勿使用'send("' + USER_INPUT_HERE + '");' to trigger your function.触发你的功能。 This makes your application vulnerable to script injections.这会使您的应用程序容易受到脚本注入的攻击。 Use JSON.stringify(USER_INPUT_HERE) to correctly escape the string.使用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 = '';
});

Example of the vulnerability:漏洞示例:
User input: " + (function(){while(1)chrome.tabs.create({url:"http://evil.com"})}()) + "用户输入: " + (function(){while(1)chrome.tabs.create({url:"http://evil.com"})}()) + "


Objects created by the extension are never passed to a page.扩展创建的对象永远不会传递到页面。 Properties and property descriptors added to an event are lost when passed to the page.添加到事件的属性和属性描述符在传递给页面时会丢失。 Instead of a content script, I advise to use an injected script What is the difference between an injected script, Content script and extension code?我建议使用注入脚本而不是内容脚本注入脚本、内容脚本和扩展代码之间有什么区别? to get the desired effect:获得预期效果:

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

For clarification, the previous snippet results in the following code to be injected in the page:为了清楚起见,前面的代码片段导致将以下代码注入到页面中:

(function(message) { /* logic of send */ })("user input");

The Event object is constructed and passed within Gmail's page, so that all properties are preserved, as if you used the console to execute the script. Event 对象是在 Gmail 的页面中构造和传递的,因此所有属性都被保留,就好像您使用控制台执行脚本一样。 It does not run in the context of your extension any more .它不再在您的扩展上下文中运行

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM