Расширение Chrome, установленное на "run at ""document start", работает слишком быстро?

EDIT: что-то было не так с моим браузером Chrome и создание конфликта с моим скриптом, полная переустановка устранена независимо от источника проблемы. Если мне случится узнать, что вызвало это, я включу его сюда.

EDIT2: просто, чтобы кто-нибудь, читающий это в 2017 году, знал, что я этого не забыл, и у меня никогда не было этой проблемы с момента моего предыдущего редактирования.


я учился, как создать простое расширение Chrome, которое является порт юзерскрипта. Скрипт отлично работает с Tampermonkey с настройкой run at to document-start, все необходимые события, которые должны быть пойманы с самого начала все захвачены.

однако, когда я установил те же настройки в расширении Chrome, я обнаружил, что тот же параметр работает быстрее, чем Tampermonkey, что приводит к сбою первой функции: (Uncaught TypeError: Cannot call method 'appendChild' of null.), поскольку он пытается добавить элемент сценария к head раздел, который не существует до 0.010 s позже.

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

есть ли способ, которым я могу сделать эту работу правильно, не прибегая к setInterval или, может быть, повторить Tampermonkey в grant none опция, которая, как представляется, запускает userscript в контексте веб-страницы?

ниже приведен мой манифест.формат JSON файл:

{
    "manifest_version": 2,
    "content_scripts": [ {
        "js":        [ "simpleuserscript.user.js" ],
        "matches":   [ "https://www.google.com/*"],
        "run_at":    "document_start"
    } ],
    "converted_from_user_script": true,
    "description":  "Chrome extension",
    "name":         "Testing",
    "version":      "1"
}

всего этого можно было бы избежать, если бы Chrome принял afterscriptexecute событие, но пока это не произойдет, я застрял с load событие. Заранее благодарю за любую помощь.


EDIT: я уже пробовал предложения в ответах: используя другой run at точка, используя DOMContentLoaded и добавить document.documentElement. Все были неудачными, потому что: 1 и 2 заставляют скрипт пропускать ранние события, а 3 возвращает тот же TypeError, что и при попытке добавить в document.head.

скрипт должен быть вставлен/бег, когда document.readyState = loading или же он пропустит ранние необходимые события, но не так рано, чтобы быть неспособным добавить Чайлдса к любому documentElementили head

пример кода внутри simpleuserscript.user.js:

var script = document.createElement("script");
script.textContent = "console.log('success')";
if(document.head) {
    document.head.appendChild(script);
} else if(document.documentElement) {
    document.documentElement.appendChild(script);
}

2 ответов


расширение для Chrome сценарии (запускается с manifest.json), которые выполняются в document_start, do огонь до document.readyStateDoc достиг interactive -- это самое раннее, что вы хотите начать возиться с большинством элементов страницы.

тем не менее, вы можете ввести большинство <script> узлы сразу, если вы хотите. Только не document.head или document.body потому что они еще не существует.
Добавить в documentElement вместо. Для пример:

var s = document.createElement ("script");
s.src = "http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js";
s.async = false;
document.documentElement.appendChild (s);

или

var s = document.createElement ("script");
s.src = chrome.extension.getURL ("MyPwnCode.js");
s.async = false;
document.documentElement.appendChild (s);

если вы добавляете или изменяете другое элементы DOM, в скрипте, работающем на document_start подождите, пока DOMContentLoaded событие вот так:

document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);

function fireContentLoadedEvent () {
    console.log ("DOMContentLoaded");
    // PUT YOUR CODE HERE.
    //document.body.textContent = "Changed this!";
}

ваша проблема в том, что при использовании "run_at": "document_start", единственным элементом, который предоставляется для существования в DOM, является <html> элемент. Если вы хотите избежать ошибок относительно загрузки страницы, например, при попытке доступа к элементу, который еще не создан, вам придется либо:

  • сделайте свой скрипт работать на "document_idle" или "document_end". Хотя "document_end" все еще не предоставляет вам, что все элементы и ресурсы страницы были полностью загружены (но DOM уже был синтаксический анализ), то "document_idle" ключевое слово даст вам уверенность в том, что DOM был проанализирован, и все элементы и ресурсы были правильно загружены до запуска скрипта.

  • или, вместо этого, вы можете продолжать использовать "document_start" упаковка кода внутри "DOMContentLoaded" прослушиватель, который заставит его работать, когда DOM полностью закончит загрузку и синтаксический анализ, аналогично "document_idle". Вот пример:

    document.addEventListener("DOMContentLoaded", function() {
        // Run your code here...
    });