Как получить доступ к веб-странице DOM, а не к странице расширения DOM? - PullRequest
61 голосов
/ 26 декабря 2010

Я пишу расширение для Chrome и пытаюсь наложить <div> поверх текущей веб-страницы, как только кнопка будет нажата в файле popup.html.

Когда я получаю доступ к методу document.body.insertBefore из popup.html, он перекрывает <div> во всплывающем окне, а не на текущей веб-странице.

Нужно ли использовать обмен сообщениями между background.html и popup.html для доступа к DOM веб-страницы? Я хотел бы сделать все в popup.html, а также по возможности использовать jQuery.

1 Ответ

102 голосов
/ 26 декабря 2010

Как указано в Обзор расширений Chrome: архитектура (которую необходимо прочитать):

Если вашему расширению нужно взаимодействовать с веб-страницами, то ононужен скрипт контента. Скрипт контента - это некоторый JavaScript, который выполняется в контексте страницы, которая была загружена в браузер.Считайте, что скрипт содержимого является частью этой загруженной страницы, а не частью расширения, с которым он был упакован (его родительское расширение).

Всплывающее окно browserAction - это страница, которую вы видите, когда нажимаете значокна панели инструментов браузера это HTML-страница с URL-адресом chrome-extension://, поэтому при доступе к ее DOM вы воздействуете на всплывающее окно.То же самое относится и к странице фона / опций расширения.

Для доступа к DOM веб-страницы и манипулирования им доступны два способа:

  1. Либо объявите сценарий (и) содержимого в manifest.json и используйте сообщения :

    chrome.tabs.sendMessage() из фоновой / всплывающей страницы в прослушиватель chrome.runtime.onMessage внедренного скрипта содержимого, который будет выполнять действия с веб-страницей и передавать результаты посредством sendResponse обратного вызова согласно документации (примечание: только JSON-ifiableподдерживаются такие объекты, как числа, строки, массивы, простые объекты, что означает не элементы DOM, не классы и не функции).Если сценарий содержимого должен инициировать связь со страницей расширения, он должен использовать chrome.runtime.sendMessage().

  2. Или использовать Tabs API для вставки скрипта содержимого :
    chrome.tabs.executeScript(tabId, details, callback)

    • Требуется разрешения : "tabs", "https://www.example.com/*"
      (или "<all_urls>" и варианты, такие как "*://*/*", "http://*/*", "https://*/*")

    • В случае явной активации пользователя лучше использовать "activeTab" разрешение вместо "tabs" и "<all_urls>", поскольку оно служит альтернативой для многих вариантов использования "<all_urls>", но не отображает предупреждающее сообщение во время установки .

    • .executeScript() может использоваться с функцией обратного вызова, которая получает массив последних оцененных выражений в сценарии с внедренным содержимым, по одному элементу на каждый кадр, в который он вводится на вкладке.Chrome использует JSON.parse() и JSON.stringify() для внутренних результатов, ограничивая поддерживаемые типы простыми объектами и простыми строковыми значениями, такими как число / строка или их массивы.
      Так что он не работает для элементов, функций DOM,пользовательские свойства, методы получения / установки: вам нужно вручную отобразить / извлечь необходимые данные и передать их в виде простого массива / объекта.

Сценарии содержимого выполняются в специальной среде, называемой изолированным миром. Они имеют доступ к DOM страницы, в которую они внедрены, но не к любым переменным или функциям JavaScript, созданным этой страницей.Каждый скрипт содержимого выглядит так, как будто на странице, на которой он запущен, нет другого JavaScript-кода.То же самое верно и в обратном: JavaScript, работающий на странице, не может вызывать какие-либо функции или обращаться к любым переменным, определенным сценариями содержимого.

Все еще возможно пойти на более глубокий уровень и получить доступ к веб-странице JavaScriptпеременные / функции .



В качестве примера второго метода покажем, что div при нажатии действия браузера.
Мы будемиспользуйте chrome.tabs.executeScript() в обработчике кликов browserAction, чтобы внедрить файл сценария содержимого (или строку литерального кода, если он маленький, см. документацию метода) в DOM этой страницы.

var someVar = {text: 'test', foo: 1, bar: false};
chrome.tabs.executeScript({
    code: '(' + function(params) {
        document.body.insertAdjacentHTML('beforeend',
            '<div style="all:unset; position:fixed; left:0; top:0; right:0; bottom:0;' +
                'background-color:rgba(0,255,0,0.3)">' + params.text + '</div>'
        );
        return {success: true, html: document.body.innerHTML};
    } + ')(' + JSON.stringify(someVar) + ');'
}, function(results) {
    console.log(results[0]);
});

Как вы можете видеть, мы использовали автоматическое преобразование строки кода функции, чтобы иметь возможность писать введенный код как обычный JavaScript с подсветкой синтаксиса и линированием.Очевидным недостатком является то, что браузер тратит время на синтаксический анализ кода, но обычно это менее 1 миллисекунды, поэтому он незначителен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...