選択内容に基づいて Chrome コンテキスト メニューにエントリを作成しようとしています。Stackoverflow でこれに関するいくつかの質問を見つけましたが、そのすべてに対する答えは、現在の選択を見てコンテキスト メニューを作成する「マウスダウン」リスナーを備えたコンテンツ スクリプトを使用することです。
これを実装しましたが、常に機能するとは限りません。すべてのログ メッセージで、コンテキスト メニューが意図したとおりに変更されたと表示されることがありますが、表示されるコンテキスト メニューは更新されません。
これに基づいて、競合状態であると考えました。コードが完全に実行される前に、chrome がコンテキスト メニューのレンダリングを開始することがあります。
「contextmenu」と「mouseup」にeventListenerを追加してみました。後者は、ユーザーがマウスでテキストを選択したときにトリガーされるため、コンテキストメニューが表示されるずっと前に (数秒でも) 変更されます。この手法を使用しても、同じエラーが発生しています。
これは、Chrome 22.0.1229.94 (Mac) で頻繁に発生し、Chromium 20.0.1132.47 (Linux) で時々発生し、Windows (Chrome 22.0.1229.94) では 2 分間試行しても発生しませんでした。
正確に何が起こっているのですか?どうすれば修正できますか?他の回避策はありますか?
これは私のコードの簡略化されたバージョンです (ログメッセージを保持しているため、それほど単純ではありません):
マニフェスト.json:
{
"name": "Test",
"version": "0.1",
"permissions": ["contextMenus"],
"content_scripts": [{
"matches": ["http://*/*", "https://*/*"],
"js": ["content_script.js"]
}],
"background": {
"scripts": ["background.js"]
},
"manifest_version": 2
}
content_script.js
function loadContextMenu() {
var selection = window.getSelection().toString().trim();
chrome.extension.sendMessage({request: 'loadContextMenu', selection: selection}, function (response) {
console.log('sendMessage callback');
});
}
document.addEventListener('mousedown', function(event){
if (event.button == 2) {
loadContextMenu();
}
}, true);
background.js
function SelectionType(str) {
if (str.match("^[0-9]+$"))
return "number";
else if (str.match("^[a-z]+$"))
return "lowercase string";
else
return "other";
}
chrome.extension.onMessage.addListener(function(msg, sender, sendResponse) {
console.log("msg.request = " + msg.request);
if (msg.request == "loadContextMenu") {
var type = SelectionType(msg.selection);
console.log("selection = " + msg.selection + ", type = " + type);
if (type == "number" || type == "lowercase string") {
console.log("Creating context menu with title = " + type);
chrome.contextMenus.removeAll(function() {
console.log("contextMenus.removeAll callback");
chrome.contextMenus.create(
{"title": type,
"contexts": ["selection"],
"onclick": function(info, tab) {alert(1);}},
function() {
console.log("ContextMenu.create callback! Error? " + chrome.extension.lastError);});
});
} else {
console.log("Removing context menu")
chrome.contextMenus.removeAll(function() {
console.log("contextMenus.removeAll callback");
});
}
console.log("handling message 'loadContextMenu' done.");
}
sendResponse({});
});