4

Gmail チャットとやり取りし、開いているすべてのチャットに同じメッセージを送信できる Google Chrome 拡張機能を実行しています。機能的な部分は完了していますが、keydownイベントをテキストエリアに送信できません。

私がやっていることはpage_action、ユーザーが Gmail にアクセスしたときに拡張アイコンを表示するために使用しています。ユーザーが拡張アイコンをクリックすると、テキストエリアを含むポップアップが表示されます。ユーザーがチャットを開いてテキストエリアに何かを書き込んでからEnterキーを押すと、開かれた各チャットのテキストエリアに同じメッセージが表示され、イベントを発生させると思われ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;
    }
  };
});

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

コードはテキストエリアを埋めるのに問題がなかったので、すべてのテキストエリアが認識keydownされますが、スクリプトがテキストエリアを埋めた後、イベントは発生しませんでした。奇妙な部分は、send.jsコードを Google Chrome コンソールに試してみたときに、keydownイベントが正常に発生し、メッセージが送信されたときに、拡張機能で同じことを行うことができないことです。

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 に答える