Como usar o jQuery na extensão do Chrome?

128

Estou escrevendo uma extensão do Chrome. E eu quero usar jQueryna minha extensão. Não estou usando nenhuma página de plano de fundo , apenas um script de plano de fundo .

Aqui estão meus arquivos:

manifest.json

{
    "manifest_version": 2,

    "name": "Extension name",
    "description": "This extension does something,",
    "version": "0.1",

    "permissions": [
        "activeTab"
    ],

    "browser_action": {
        "default_icon": "images/icon_128.png"
    },

    "background": {
        "scripts": ["background.js"],
        "persistent": false
    },

    "icons": {
        "16": "images/icon_16.png",
        "48": "images/icon_48.png",
        "128": "images/icon_128.png"
    }
}

Meu background.jsarquivo apenas executa outro arquivo chamadowork.js

// Respond to the click on extension Icon
chrome.browserAction.onClicked.addListener(function (tab) {
    chrome.tabs.executeScript({
        file: 'work.js'
    });
});

A lógica principal da minha extensão está dentro work.js. O conteúdo do qual eu acho que não importa aqui para esta pergunta.

O que quero perguntar é como posso usar o jQuery na minha extensão. Desde que eu não estou usando nenhuma página de plano de fundo. Não posso simplesmente adicionar o jQuery a ele. Então, como posso adicionar e usar o jQuery na minha extensão?

Tentei executar o jQuery junto com o meu work.js do background.jsarquivo.

// Respond to the click on extension Icon
chrome.browserAction.onClicked.addListener(function (tab) {
    chrome.tabs.executeScript({
        file: 'thirdParty/jquery-2.0.3.js'
    });
    chrome.tabs.executeScript({
        file: 'work.js'
    });
});

E funciona bem, mas estou preocupada se os scripts adicionados a serem executados dessa maneira estão sendo executados de forma assíncrona. Se sim, pode acontecer que o work.js seja executado antes do jQuery (ou de outras bibliotecas que eu possa adicionar no futuro).

E também gostaria de saber qual é a melhor e correta maneira de usar bibliotecas de terceiros, na minha extensão do Chrome.

Ishan
fonte
2
A maneira correta é ir baunilha!
bjb568
Se você está aqui procurando como adicionar jQuery a uma extensão pop-up (como eu estava), consulte esta pergunta: stackoverflow.com/questions/12035242/…
Pro Q

Respostas:

124

Você precisa adicionar seu script jquery ao seu projeto de extensão chrome e ao diretório background seção do seu manifest.json assim:

  "background":
    {
        "scripts": ["thirdParty/jquery-2.0.3.js", "background.js"]
    }

Se você precisar de jquery em um content_scripts, precisará adicioná-lo também no manifesto:

"content_scripts": 
    [
        {
            "matches":["http://website*"],
            "js":["thirdParty/jquery.1.10.2.min.js", "script.js"],
            "css": ["css/style.css"],
            "run_at": "document_end"
        }
    ]

Foi o que eu fiz.

Além disso, se bem me lembro, os scripts em segundo plano são executados em uma janela em segundo plano pela qual você pode abrir chrome://extensions.

Nico
fonte
7
Bem, o que você quer dizer com exatamente You have to add your jquery script to your chrome-extension project? Eu fiz isso: manifest.json: "background": { `" scripts ": [" thirdParty / jquery-2.0.3.js "," background.js "],` `" persistent ": false``}, `e baixei o jQuery para a pasta ThirdParty. No entanto, ainda não consigo usar o jQuery. Ele deu o erro: Uncaught ReferenceError: $ is not defined adicionei isso ao meu work.jsarquivo para teste. $("body").html("Foo!");
Ishan
O comentário acima parece uma bagunça, mas ao adicionar comentários, a visualização não é mostrada. Por favor, perdoe-me por isso.
Ishan
Quero adicioná-lo à sua pasta de extensão do chrome. Como /home/you/chromexetension_source_files/thirdParty/jquery-2.0.3.js. Você deve fazer o mesmo com o seu work.js.
Nico
1
Eu tentei fazer o que você disse. Mas ainda estou recebendo o mesmo erro de não conseguir acessar o jquery do meu work.jsarquivo. Uncaught ReferenceError: $ is not defined. Se puder, faça o upload de um exemplo de trabalho em algum lugar. Apenas um exemplo simples, como '$ ("body"). Html ("Foo!");' em work.js.
Ishan
7
Eu também tive problemas para ser reconhecido jQueryou $reconhecido. Descobri que eu estava fazendo referência ao jQuery por último na matriz de manifesto. Quando o coloquei pela primeira vez, foi reconhecido.
precisa saber é
18

É muito fácil, basta fazer o seguinte:

adicione a seguinte linha no seu manifest.json

"content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'",

Agora você pode carregar o jQuery diretamente do URL

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>

Fonte: google doc

Vikas Bansal
fonte
1
E se você tiver vários scripts para carregar?
outro
1
Ótima resposta se você deseja carregar seu script de um servidor remoto (o que exige efetivamente que você confie no servidor remoto com sua extensão e tudo o que ele tem acesso).
Nathaniel Verhaaren
1
@NathanielVerhaaren Este é um ponto razoável a ser levantado, mas pode ser atenuado verificando a fonte usando subresource integrity(SRI).
Dan Atkinson
13

E funciona bem, mas estou com a preocupação de saber se os scripts adicionados a serem executados dessa maneira estão sendo executados de forma assíncrona. Se sim, pode acontecer que o work.js seja executado antes do jQuery (ou de outras bibliotecas que eu possa adicionar no futuro).

Isso realmente não deveria ser uma preocupação: você enfileira os scripts para serem executados em um determinado contexto JS, e esse contexto não pode ter uma condição de corrida, pois é de thread único.

No entanto, a maneira correta de eliminar essa preocupação é encadear as chamadas:

chrome.browserAction.onClicked.addListener(function (tab) {
    chrome.tabs.executeScript({
        file: 'thirdParty/jquery-2.0.3.js'
    }, function() {
        // Guaranteed to execute only after the previous script returns
        chrome.tabs.executeScript({
            file: 'work.js'
        });
    });
});

Ou, generalizado:

function injectScripts(scripts, callback) {
  if(scripts.length) {
    var script = scripts.shift();
    chrome.tabs.executeScript({file: script}, function() {
      if(chrome.runtime.lastError && typeof callback === "function") {
        callback(false); // Injection failed
      }
      injectScripts(scripts, callback);
    });
  } else {
    if(typeof callback === "function") {
      callback(true);
    }
  }
}

injectScripts(["thirdParty/jquery-2.0.3.js", "work.js"], doSomethingElse);

Ou, prometido (e alinhado mais com a assinatura adequada):

function injectScript(tabId, injectDetails) {
  return new Promise((resolve, reject) => {
    chrome.tabs.executeScript(tabId, injectDetails, (data) => {
      if (chrome.runtime.lastError) {
        reject(chrome.runtime.lastError.message);
      } else {
        resolve(data);
      }
    });
  });
}

injectScript(null, {file: "thirdParty/jquery-2.0.3.js"}).then(
  () => injectScript(null, {file: "work.js"})
).then(
  () => doSomethingElse
).catch(
  (error) => console.error(error)
);

Ou, por que diabos não, async/ await-ed para uma sintaxe ainda mais clara:

function injectScript(tabId, injectDetails) {
  return new Promise((resolve, reject) => {
    chrome.tabs.executeScript(tabId, injectDetails, (data) => {
      if (chrome.runtime.lastError) {
        reject(chrome.runtime.lastError.message);
      } else {
        resolve(data);
      }
    });
  });
}

try {
  await injectScript(null, {file: "thirdParty/jquery-2.0.3.js"});
  await injectScript(null, {file: "work.js"});
  doSomethingElse();
} catch (err) {
  console.error(err);
}

Observe que no Firefox você pode simplesmente usar browser.tabs.executeScript, pois retornará uma promessa.

Xan
fonte
O primeiro método é brilhante. Como alguém que não conhece muito JavaScript, nunca considerei algo assim.
FriskySaga 21/03
11

Além das soluções já mencionadas, você também pode fazer o download jquery.min.jslocalmente e usá-lo -

Para download -

wget "https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"

manifest.json -

"content_scripts": [
   {
    "js": ["/path/to/jquery.min.js", ...]
   }
],

em html -

<script src="/path/to/jquery.min.js"></script>

Referência - https://developer.chrome.com/extensions/contentSecurityPolicy

Arik Pamnani
fonte
3
Esta é a melhor maneira ... Você não precisa da parte html.
c-an
1

No meu caso, obtive uma solução funcional por meio do CrossDocument Messaging (XDM) e da execução do Chrome na extensão onclick, em vez do carregamento da página.

manifest.json

{
  "name": "JQuery Light",
  "version": "1",
  "manifest_version": 2,

  "browser_action": {
    "default_icon": "icon.png"
  },

  "content_scripts": [
    {
      "matches": [
        "https://*.google.com/*"
      ],
      "js": [
        "jquery-3.3.1.min.js",
        "myscript.js"
      ]
    }
  ],

  "background": {
    "scripts": [
      "background.js"
    ]
  }

}

background.js

chrome.browserAction.onClicked.addListener(function (tab) {
  chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
    var activeTab = tabs[0];
    chrome.tabs.sendMessage(activeTab.id, {"message": "clicked_browser_action"});
  });
});

myscript.js

chrome.runtime.onMessage.addListener(
    function (request, sender, sendResponse) {
        if (request.message === "clicked_browser_action") {
        console.log('Hello world!')
        }
    }
);
Ruslan Novikov
fonte