Загрузка внешнего JavaScript в расширение Google Chrome

Я пишу расширение Google Chrome, которое управляет текущей страницей (в основном добавляет кнопку).

В моем скрипте контента я хочу загрузить API Graph Facebook:

$fbDiv = $(document.createElement('div')).attr('id', 'fb-root');
$fbScript = $(document.createElement('script')).attr('src', 'https://connect.facebook.net/en_US/all.js');
$(body).append($fbDiv);
$(body).append($fbScript);

console.log("fbScript: " + typeof $fbScript.get(0));
console.log("fbScript parent: " + typeof $fbScript.parent().get(0));
console.log("find through body: " + typeof $(body).find($fbScript.get(0)).get(0));

Однако сценарий, похоже, не добавлен в body, Вот консольный журнал:

fbScript: object
fbScript parent: undefined
find through body: undefined

Есть идеи, что я делаю не так?

2 ответа

Решение

Проблема заключается в том, что JavaScript внутри скриптов контента работает в собственной изолированной среде и имеет доступ только к другому JavaScript, который был загружен одним из двух способов:

Через манифест:

{
  "name": "My extension",
  ...
  "content_scripts": [
    {
      "js": ["https://connect.facebook.net/en_US/all.js"]
    }
  ],
  ...
}

Или с помощью программной инъекции:

/* in background.html */
chrome.browserAction.onClicked.addListener(function(tab) {
    chrome.tabs.executeScript(null,
                       {file:"https://connect.facebook.net/en_US/all.js"});
});

Обязательно обновите ваши разрешения для манифеста:

/* in manifest.json */
"permissions": [
    "tabs", "https://connect.facebook.net"
 ], 

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

Кроме того, поскольку сценарий FB требует, чтобы в DOM был "fb-root", вам, вероятно, потребуется использовать программный подход, чтобы вы могли сначала обновить DOM с помощью элемента, а затем передать сообщение обратно на фоновую страницу, чтобы загрузите скрипт Facebook, чтобы он был доступен для JavaScript, который загружен в скрипты контента.

Расширения Google Chrome больше не позволяют вводить внешний код напрямую, однако вы все равно можете загрузить код с помощью вызова Ajax и передать его инжектору, как если бы он был блоком кода.

chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
    $.get("http://127.0.0.1:8000/static/plugin/somesite.js", function(result) {
        chrome.tabs.executeScript(tabs[0].id, {code: result});
    }, "text");
});

источник: /questions/4638857/rasshirenie-chrome-zagruzite-i-vyipolnite-vneshnij-skript/4638876#4638876

Если вы хотите загрузить его как сценарий содержимого:

fetch('https://example.com/content.js')
  .then(resp => resp.text())
  .then(eval)
  .catch(console.error)

Если вы хотите загрузить его как фоновый скрипт. Возьмем, к примеру, https://example.com/bg.js.

  1. добавьте удаленный js-скрипт в файл фоновой страницы, который здесь называется background.html
<!DOCTYPE html>
<html>
<head>
  <script src="https://example.com/bg.js"></script>
</head>
<body>
<div>Empty content</div>
</body>
</html>
  1. добавьте https://example.com в content_security_policy файла manifest.json:
"background": {
  "page": "background.html"
},
"content_security_policy": "script-src 'self' https://example.com ; object-src 'self'",

Требования:

  1. Удаленный скрипт js должен обслуживаться через https вместо http.
  2. Вы должны указать страницу, а не массив скриптов в фоновом разделе
Другие вопросы по тегам