Greasemonkey: WebExt: execute scripts em todos os três tempos de execução

Criado em 27 fev. 2017  ·  6Comentários  ·  Fonte: greasemonkey/greasemonkey

Elabore um plano de trabalho sobre como executar scripts de usuário, obviamente não conhecido até o tempo de execução. Compatível com todos os três tempos de execução - criticamente document_start .

Veja https://github.com/arantius/greasemonkey/tree/8a255bde1aa6312715740fd0157d582a2d6cb183 para minha pesquisa até agora, onde a abordagem é:

  • Use um script de plano de fundo. (Ele terá acesso ao armazenamento / quaisquer APIs, onde os scripts são armazenados, para que possa saber o conteúdo dos scripts a serem executados.)
  • Observe algo (o quê? ) Para acionar ..
  • .. chame tabs.executeScript() para disparar cada script de usuário.

Isso "funciona", exceto por nenhum evento que ainda encontrei para observar que funcione para todos os três tempos de execução. Há webNavigation 's onBeforeNavigate que na verdade é muito cedo , ele (como o nome indica) dispara antes da navegação, quando o documento atual ainda está ativo. Mas o próximo ponto é onCommitted , e nesse ponto é tarde demais para iniciar, os scripts embutidos já foram executados.

wontfix

Todos 6 comentários

Pesquisar:

  • Observe webRequest vez de webNavigation . Isso nos dá um controle sobre o tempo de início?
  • Injete um script de conteúdo webext, em document_start, para cada página. Faça com que ele saiba de alguma forma quais scripts executar, de forma síncrona. (Porque qualquer coisa assíncrona nos empurra para além do horário de início.)

Re: https://bugzilla.mozilla.org/show_bug.cgi?id=1332273#c8

Gostaria de poder armazenar (em segundo plano) um blob, depois obter (apenas) sua URL e passar essa URL (de forma síncrona) para o (s) script (s) de conteúdo, mas não conheço nenhuma maneira de fazer qualquer uma dessas coisas.

Não resolvi todos os detalhes sozinho, mas acho que a página de plano de fundo poderia armazenar blobs em IndexedDB, convertê-los em URIs de blob via URL.createObjectURL () no momento da inicialização e passá-los para a API de configuração síncrona hipotética e então talvez carregue-os via

O IndexedDB não está desabilitado no modo de

Não acho que isso afete o (s) script (s) de fundo?

Isso é possível usando um script de conteúdo que é executado em document_start e se parece com isto: (possivelmente não funcionará para guias já carregadas, use jQuery para isso)

// execute `document_start` scripts here...

document.addEventListener("DOMContentLoaded", event => {
    // execute `document_end` scripts here...
});

window.addEventListener("load", event => {
    // execute `document_idle` scripts here...
});

ou algo assim: (pode ser mais sujeito a erros)

let run = [false, false, false];

document_start();

if (document.readyState === "complete") {
    document_idle();
} else if (document.readyState === "interactive") {
    document_end();
}

document.onreadystatechange = () => {
    switch (document.readyState) {
        case "loading":     break;
        case "interactive": document_end();
        case "complete":    document_idle();
    }
};

function document_start() {
    if (run[0]) return;
    run[0] = true;

    // execute `document_start` scripts here...
}

function document_end() {
    if (!run[0]) document_start();
    if (run[1])  return;
    run[1] = true;

    // execute `document_end` scripts here...
}

function document_idle() {
    if (!run[1]) document_end();
    if (run[2])  return;
    run[2] = true;

    // execute `document_idle` scripts here...
}

Outra maneira é usar três scripts de conteúdo separados, onde cada um deles é executado em um momento diferente.
Para isso, o manifest.json contém o seguinte: (provavelmente funcionará provavelmente (pode haver uma condição de corrida))

"content_scripts": [
    {
        "matches": ["<all_urls>"],
        "run_at": "document_start",
        "js": ["document_start_handler.js"]
    },
    {
        "matches": ["<all_urls>"],
        "run_at": "document_end",
        "js": ["document_end_handler.js"]
    },
    {
        "matches": ["<all_urls>"],
        "run_at": "document_idle",
        "js": ["document_idle_handler.js"]
    }
]

Também é possível usar jQuery, que pode ser a maneira menos propensa a erros, mas tudo isso precisa de testes extensivos: (novamente, é executado em document_start mas precisa ser empacotado com jQuery)

function document_start() {
    // execute `document_start` scripts here...
}

function document_end() {
    // execute `document_end` scripts here...
}

function document_idle() {
    // execute `document_idle` scripts here...
}

// Use jQuery to execute all the functions:
document_start();

// `$(document).ready(document_end)` is deprecated since 3.0
$(document_end);

// jQuery used to have a method for this: `$(window).load(document_idle)`
if (document.readyState === "complete") {
    document_idle();
} else {
    $(window).on("load", document_idle);
}

Conforme está escrito, este problema é muito amplo. Estou dividindo isso em problemas separados para serem rastreados com mais facilidade:

2525, # 2526

Esta página foi útil?
0 / 5 - 0 avaliações