2016-07-25 1 views
1

Я работаю над расширением браузера/надстройкой. Мы работаем в Chrome, поэтому я пытаюсь заставить его работать в Firefox.Как я могу сделать надстройку addcript надстройки firefox и запустить скрипт перед другими скриптами страниц?

Я получил надстройку для загрузки в Firefox Developer Edition 49.0a2 (2016-07-25).

Мое расширение включает в себя набор content_script для run_at: document_start, поэтому он может вставлять тег сценария перед запуском других скриптов страниц, чтобы он мог сделать объект глобально доступным для веб-сайтов.

Это, как показалось, отлично работает в Chrome, но в Firefox он оказался немного гоночным, с большей загрузкой других ресурсов страницы.

Есть ли стратегия загрузки сценария контента так, чтобы он мог вводить & загрузку скрипта перед запуском любых других скриптов страницы?

Когда я добавляю журналы, я могу изолировать то, что происходит довольно красиво. В этом примере контент-скрипт:

// inject in-page script 
console.log('STEP 1, this always happens first') 
var scriptTag = document.createElement('script') 
scriptTag.src = chrome.extension.getURL('scripts/inpage.js') 
scriptTag.onload = function() { this.parentNode.removeChild(this) } 
var container = document.head || document.documentElement 
// append as first child 
container.insertBefore(scriptTag, container.children[0]) 

Теперь, если файл scripts/inpage.js просто запускает журнал, как

console.log('STEP 2, this should always run second') 

И я посещаю страницу со скриптом, как это:

console.log('Step 3, the page itself, should run last') 

На практике шаги 2 и 3 выполняются в недетерминированном порядке.

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

У меня есть Firefox-совместимая версия сценария в публичном хранилище на специальном отделение, если вы решитесь попробовать сам: https://github.com/MetaMask/metamask-plugin/tree/FirefoxCompatibility

+0

Это строка, в которой я добавляю тег скрипта на текущую страницу. Когда я делаю это с помощью журналов, я вижу, что этот код запускается до скрипта страницы, но сам сценарий с инъекциями не всегда запускается до скриптов страниц. https://github.com/MetaMask/metamask-plugin/blob/FirefoxCompatibility/app/scripts/contentscript.js#L20 – DanF

ответ

3

динамически вставляются скрипт с внешним источником (<script src>) не делает блок выполнение скриптов, поэтому нет никакой гарантии, что ваш скрипт загрузится. Если ваше расширение работало в Chrome, это было просто удачей.

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

var actualCode = ` 
// Content of scripts/inpage.js here 
`; 

var s = document.createElement('script'); 
s.textContent = actualCode; 
(document.head || document.documentElement).appendChild(s); 
s.remove(); 

В идеале, ваш сценарий сборки будет читать scripts/inpage.js, сериализации его в строку и поместить его в actualCode переменная. Но если inpage.js - всего несколько строк кода, то можно использовать приведенное выше.

Обратите внимание: не должен вводить код на веб-страницу, если это абсолютно необходимо. Причина этого в том, что среда выполнения страницы не доверена. Если вы вводите значение document_start, вы можете сохранять функции и (прототипы) методы, которые используются для более поздних (в закрытии), но требуется очень тщательное кодирование.

Если ваш скрипт контента не сгенерирован скриптом сборки, и вы все же хотите, чтобы сценарии были раздельными, вы также можете использовать синхронный XMLHttpRequest для извлечения сценария. Синхронный XHR устарел по соображениям производительности, поэтому используйте его на свой страх и риск.Код Расширение обычно в комплекте с расширением, поэтому использование синхронизации XHR должно быть низким уровнем риска:

// Note: do not use synchronous XHR in production! 
var x = new XMLHttpRequest(); 
x.open('GET', chrome.runtime.getURL('scripts/inpage.js'), false); 
x.send(); 
var actualCode = x.responseText; 

var s = document.createElement('script'); 
s.textContent = actualCode; 
(document.head || document.documentElement).appendChild(s); 
s.remove(); 
+0

Я просто добавлю примечание, что в IRC вы также указали, что FireFox предоставляет дополнительные способы для чистого выполнения мои цели: выставлять API на главную страницу из файла содержимого через посредников экспорта: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction – DanF

+1

@ DanF 'Component.utils.exportFunction' и т. Д. Еще не доступны (и они ** не станут доступными в пространстве имен' Components', а WebExtensions ** не могут использовать '' Компоненты '**). Когда патч на https://bugzil.la/1280482 приземляется, вы можете получить ту же функциональность, используя глобальный метод 'exportFunction'. –

0

Если вы используете аддон на основе bootstrap.js вы можете использовать FrameScript и DOMWindowCreated работать с документом прежде чем даже HTML DOM (прошлые основы document.body и т. д.) отображает - https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Frame_script_environment#Events - внутреннийHTML будет доступен, но скрипт не будет выполнен. Вы можете поместить свой встроенный скрипт вверху, как упоминал @Rob.

Смежные вопросы