4

我正在做一个与 Gmail 聊天交互的谷歌浏览器扩展,可以向所有打开的聊天发送相同的消息,功能部分已完成,但我无法将keydown事件发送到 textareas。

我正在做的是page_action在用户访问 Gmail 时使用 a 来显示扩展图标。当用户点击扩展图标时,会弹出一个带有 textarea 的弹出窗口,当用户打开聊天并在 textarea 中写入内容然后Enter按键时,每个打开的聊天的 textarea 将填充相同的消息和应该触发keydown事件。

这是基本代码:

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

发送.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,但keydown在脚本填充 textareas 后事件没有触发。奇怪的是,当我在 Google Chrome 控制台中尝试send.jskeydown代码时,事件正常触发并且消息已发送,但我无法对扩展程序做同样的事情。

那么,如何将keydown事件触发到扩展中?

4

1 回答 1

2

Gmail 由框架组成。
默认情况下,chrome.tabs.executeScript仅在主(顶部窗口)框架中注入代码。要在子帧中也注入代码,请添加allFrames: true到您的详细信息。

另外,不要用来触发'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"})}()) + "


扩展创建的对象永远不会传递给页面。添加到事件的属性和属性描述符在传递到页面时会丢失。我建议不要使用内容脚本,而是使用注入脚本 注入脚本、内容脚本和扩展代码有什么区别?获得预期的效果:

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

为澄清起见,前面的代码片段导致将以下代码注入页面:

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

Event 对象在 Gmail 页面中构建和传递,因此所有属性都被保留,就像您使用控制台执行脚本一样。它不再在您的扩展的上下文中运行

于 2012-06-23T20:13:48.933 回答