Контекстное меню расширения Chrome: как добавить div на страницу после нажатия пункта меню

Игра с созданием расширения Chrome. На данный момент я собрал элемент контекстного меню. Когда щелкнут элемент контекстного меню, он запускает itemClicked() в фоновом режиме script context_menu.js:

function itemClicked(info, tab) {
     alert("clicked");
}

Предупреждение срабатывает. Я также могу делать такие вещи, как отправка запросов ajax через itemClicked()

Однако я не могу добавить какие-либо элементы на страницу (или манипуляции DOM любого типа). Даже что-то основное, как это не работает:

  var d = document.createElement('div');
  d.setAttribute("css", "width: 100px; height: 100px; background-color: red; position: fixed; top: 70px; left: 30px; z-index: 99999999999;");
  document.body.appendChild(d); 

Итак, я попытался добавить тот же код в контент script:

chrome.contextMenus.onClicked.addListener(function(OnClickData info, tabs.Tab tab) {
  //code to append the input here
});

Но это все равно не сработает. Что я делаю неправильно?

Как я могу заставить контекстное меню добавить что-то на страницу после нажатия?

Большое спасибо!

Изменить: вот мой manifest.json(удалить ненужные вещи, такие как имя/описание... и т.д.)

{


  "permissions": [
    "activeTab",        
    "tabs",
    "cookies",
    "contextMenus"
  ],

  "background": {
    "scripts": ["context_menu.js"]
  },
  "browser_action": {
    "default_icon": "icon16.png",
    "default_css": "popup.css",
    "default_popup": "popup.html"
  },

  "content_scripts": [
    {      
      "matches": ["<all_urls>"],
      "js": ["vendor/jquery-1.8.2.min.js", "config.js", "content_script.js"]   
    }
  ],

  "web_accessible_resources": ["popup.html"]

}

Ответ 1

Вероятно, вы неправильно поняли концепцию фоновой страницы (и ее младшего, более удобного для пользователя и привилегированного родного брата: страница событий) и script.

контент scritps:

  • привязаны к определенной веб-странице, загруженной в вкладку.
  • Живите в изолированном мире (контекст JS), но имеете прямой доступ к веб-страницам DOM.
  • Может связываться с фоновой страницей (см. Передача сообщений).

фоновые страницы:

  • Связаны с вашим расширением (для каждого расширения есть 1 страница фона (или события)).
  • Всегда где-то в фоновом режиме (страницы событий "вздремнут" время от времени, но вы всегда можете их разбудить).
  • У вас нет прямого доступа к любой веб-странице.
  • Может взаимодействовать с скриптами содержимого (и другими представлениями) (см. Передача сообщений).
  • Может делать классные вещи (потому что у них есть доступ к прохладным хром. * API).

API chrome.contentMenus доступен только для фоновой страницы. Таким образом, вам нужно создать любое контекстное меню и прослушать onClicked события там (на странице фона).
После нажатия контекстного меню вы можете использовать Programmatic Injection, чтобы вставить некоторый код (или контент script) на активную вкладку веб-страница.

Ниже приведен исходный код примерного расширения, демонстрирующего этот метод.

manifest.json:

{
    "manifest_version": 2,
    "name":    "Test Extension",
    "version": "0.0",

    "background": {
        "persistent": false,   // <-- let make it an event page
        "scripts": ["background.js"]
    },

    "permissions": [
        "contextMenus",
        "activeTab"   // <-- here, sufficient for our purpose
    ]
}

background.js:

/* Create a context-menu */
chrome.contextMenus.create({
    id: "myContextMenu",   // <-- mandatory with event-pages
    title: "Click me",
    contexts: ["all"]
});

/* Register a listener for the `onClicked` event */
chrome.contextMenus.onClicked.addListener(function(info, tab) {
    if (tab) {
        /* Create the code to be injected */
        var code = [
            'var d = document.createElement("div");',
            'd.setAttribute("style", "'
                + 'background-color: red; '
                + 'width: 100px; '
                + 'height: 100px; '
                + 'position: fixed; '
                + 'top: 70px; '
                + 'left: 30px; '
                + 'z-index: 9999; '
                + '");',
            'document.body.appendChild(d);'
        ].join("\n");

        /* Inject the code into the current tab */
        chrome.tabs.executeScript(tab.id, { code: code });
    }
});

(Если ваш введенный код достаточно сложный, может быть лучше вставить файл .js. Дополнительная информация о Programmatic Injection.)