스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
Safari 웹 확장 프로그램의 새로운 기능
웹을 탐색하는 사용자에게 보다 우수한 경험을 제공할 수 있도록 Safari 웹 확장 프로그램의 향상된 최신 기능을 사용하는 방법을 알아보세요. 매니페스트 버전 3로 업그레이드하고, 웹 확장 프로그램용 최신 API를 도입하고, 여러 기기에서 확장 프로그램을 동기화하는 방법을 보여드리겠습니다.
리소스
- Developing a Safari Web Extension
- Learn more about bug reporting
- MDN Web Docs - Web Extensions API
- Messaging a Web Extension’s Native App
- Modernizing Safari Web Extensions
- Safari web extensions
관련 비디오
WWDC23
WWDC22
WWDC21
-
다운로드
♪♪
안녕하세요 Kiara Rose입니다 저는 Safari 확장 프로그램 엔지니어입니다 오늘 Safari 웹 확장 프로그램에 대한 새로운 소식을 전하게 되어 매우 기쁩니다 오늘 프레젠테이션을 시작하기 전에 iOS와 iPadOS macOS 확장 프로그램을 App Store에 제출해 주신 여러분께 감사의 말씀 드립니다 지속적으로 새로운 기능과 API를 구현하는 게 저희의 목표입니다 사용자들에게 더 나은 환경을 제공할 수 있도록 지원하는 거죠 오늘은 저희가 지난 1년 동안 구현한 흥미로운 기능들을 몇 가지 말씀드리려고 합니다 확장 프로그램을 위한 새로운 Manifest 버전과 업데이트된 API 여러 기기에서의 확장 프로그램 동기화입니다 Manifest 버전 3부터 시작해 보죠 Manifest 버전 3는 웹 확장 프로그램 플랫폼의 다음 버전입니다 성능 및 보안 기능을 향상시키고 보편적인 확장 프로그램 API로 통합합니다
이미 버전 3를 위해 확장 프로그램을 업데이트한 경우 여러분의 확장 프로그램은 Safari 15.4 이상에서 작동합니다 업데이트하지 않으신 분들도 걱정하실 필요 없습니다 저희가 Safari에서 Manifest 버전 2를 사용해 계속 확장 프로그램을 지원할 테니까요 Manifest 버전 3의 새 핵심 기능 중 하나는 여러분의 확장 프로그램에서 백그라운드 페이지 대신 Service Worker를 사용할 수 있단 겁니다 웹 개발자의 경우에는 Service Worker가 익숙할 겁니다 addEventListener API를 사용하여 리스너를 등록할 수 있는 이벤트를 기반으로 하는 페이지죠
Manifest 버전 3를 지원하는 다른 브라우저와도 호환됩니다 여러분이 확장 프로그램의 백그라운드 페이지를 선호한다면 사용해도 되지만 계속 쓸 수는 없을 겁니다 버전 3에서 또 달라진 점은 JavaScript 실행을 위한 API와 웹 페이지의 스타일링이 탭 API에서 새 스크립팅 API로 이동했단 겁니다 메서드의 대부분 기능은 동일하게 유지되지만 스크립팅이 제공하는 새롭게 추가된 기능이 있습니다 웹 페이지에 코드를 삽입하는 새로운 방식도 생겼고 페이지의 프레임에서 실행되는 코드 옵션도 다양해졌죠 그리고 코드가 실행되는 환경도 결정할 수 있게 됐습니다 새로운 스크립팅 API 코드와 탭 API는 어떻게 다른지 살펴보도록 하죠 저는 이 코드 스니펫에서 tabs.executeScript API를 사용해 웹 페이지의 배경색을 파란색으로 바꾸겠습니다 이 API에서는 문자열에 포함된 코드만 삽입할 수 있습니다 '코드' 프로퍼티를 전달하는 거죠 하지만 이제는 새로운 스크립팅 API를 통해서 이 코드를 포함하는 함수 객체를 전달할 수 있습니다 그리고 다른 함수와 마찬가지로 전달 가능한 인수도 포함할 수 있습니다 이는 훨씬 향상된 방법을 스크립트를 실행하는 겁니다 문자열에 코드를 쓰는 것에만 국한되지 않기 때문이죠
스크립팅에는 타깃이라는 새로운 프로퍼티가 있습니다 이는 스크립트 실행 위치를 지정하는 데 사용됩니다
스크립트를 실행하려면 스크립트를 실행하고자 하는 탭의 ID를 지정해야 합니다 탭 ID가 지정되지 않은 경우 이 API에서는 오류로 처리합니다 그러면 코드를 입력할 웹 페이지의 프레임을 선택할 때 프레임 ID를 지정할 수 있습니다 탭 API에서는 하나의 ID만 지정할 수 있습니다 하지만 스크립팅 API에선 여러 ID를 지정할 수 있죠 제가 가진 코드가 많다고 했을 때 여러 개의 파일에 담을 수 있다면 깔끔해 보이겠죠 tabs.executeScript API에서는 파일을 하나만 지정할 수 있지만 scripting.executeScript에서는 여러 개의 파일을 지정할 수 있습니다 incertCSS에서도 비슷한 작업을 수행해서 웹 페이지에 스타일을 더할 수도 있습니다 removeCSS에서도 웹 페이지의 스타일을 제거할 수 있습니다 이 API는 Manifest 버전 2와 3에서 모두 사용할 수 있습니다 하지만 tabs.executeScript API는 버전 3에서 사용할 수 없습니다 새로운 스크립팅 API 외에 다른 여러 API도 조금씩 수정됐습니다 그중 하나는 web_accessible_resources입니다
Manifest 버전 2에서는 리소스를 포함하려면 웹 페이지에 접근할 수 있는 여러 개의 파일을 전달해야 하죠 하지만 Manifest에서 지정한 모든 리소스에 대해 웹 페이지 접근을 제공하기 때문에 문제가 있을 수 있습니다
버전 3의 새로운 포맷에서는 사이트에서 사용 가능한 리소스를 제어할 수 있습니다 예시를 살펴보죠 전에는 확장 프로그램이 접근할 수 있는 모든 사이트에서 쿠키 및 파이 이미지를 사용할 수 있었습니다 하지만 버전 3부터는 apple.com URL에서만 파이 이미지를 사용할 수 있고 쿠키 이미지는 webkit.org에서만 사용할 수 있죠 이제 다음으로 살펴볼 건 browser_action과 page_action API 변경 사항입니다
Manifest 버전 2에서는 액션이 다음과 같이 분명하게 지정돼 있습니다 하지만 API가 비슷한 역할을 수행하기 때문에 버전 3에서는 하나의 API만 사용하도록 통합됐습니다 그게 액션이죠
또한 확장 프로그램을 위한 콘텐츠 보안 정책을 선언하는 방법도 업데이트했습니다 버전 2에선 확장 프로그램 정책을 문자열을 사용해 정의했습니다 하지만 버전 3에서는 'extension_pages' 키를 쓰는 객체를 사용해 정의합니다 중요하게 알아 두셔야 할 건 스크립트의 원격 소스는 버전 3에서는 더 이상 허용되지 않는단 겁니다 최종 API 변경은 사용하지 않는 browser.extension.getURL API로 변경됐습니다 이 API는 버전 3에서 더 이상 지원되지 않습니다 대신 browser.runtime에서 해당 API를 사용하세요 Manifest 버전 3에 도입된 새로운 기능에 대해 알아봤으니 이제 업데이트된 확장 프로그램의 프로세스를 살펴보겠습니다 그럼 여러분도 새 기능을 사용할 수 있죠
작년 프리젠테이션의 Sea Creator 확장 프로그램을 업데이트해서 Manifest 버전 3를 사용할 수 있게 하겠습니다
이 확장 프로그램은 '물고기'란 단어를 이모티콘으로 대체합니다
일단은 버전 2에서 버전 3로 바꾸도록 하죠
일시적인 백그라운드 페이지를 사용할 수도 있지만 저는 서비스 워커를 사용해서 업데이트하고 제 확장 프로그램이 Chrome과 호환되도록 할 겁니다
마지막으로 browser_action을 action으로 변경할 겁니다
Manifest의 구조와 관련해 얘기해 보죠 버전 3 새로운 사양과의 호환을 위해 필요한 주요 변경 사항을 말씀드리겠습니다 이걸 시험하기 위해서 확장 프로그램을 구축하고
Safari에서 사용 가능하도록 설정할 겁니다
그다음 webkit.org 블로그 페이지로 이동해서 이 확장 프로그램을 사용해 '물고기'란 단어의 인스턴스를 물고기 이모티콘으로 바꿀 겁니다
하지만 뭔가 잘못된 것 같습니다 이 페이지의 어떤 단어도 이모티콘으로 바뀌지 않았습니다 오류 메시지가 있는지 팝오버를 검사해 보죠
콘솔 탭에 오류 메시지가 보이는군요 browser.tabs.executeScript가 정의되지 않았다고 쓰여 있네요 이건 이 API를 버전 3에서 더는 쓸 수 없기 때문입니다 확장 프로그램을 업데이트해야 새 스크립팅 API를 쓸 수 있죠 Xcode에서 popup.js 파일로 돌아가서 스크립팅을 사용하도록 이 줄을 수정하겠습니다
타깃 프로퍼티를 추가할 건데 이는 스크립트를 삽입할 위치를 정하는 데 사용합니다
새로운 스크립트 API를 이용해 탭의 ID를 지정해야 합니다 현재 탭의 정보를 포함하는 객체를 불러오기 위해서 tabs.getCurrent API를 이용해 이 작업을 수행할 수 있습니다
그다음 해당 객체를 사용해 탭 ID를 검색할 수 있죠
그다음 실행할 스크립트가 포함된 파일을 추가합니다
마지막으로 Manifest에 스크립팅 권한을 추가합니다
확장 프로그램을 구축한 다음에
이런 변경 사항을 Safari에 적용합니다
보시다시피 Manifest 버전 3의 새로운 기능을 사용해 이 확장 프로그램이 Safari에서 작동됩니다 확장 프로그램을 업그레이드하는 건 간단합니다 하지만 이런 새로운 변화가 아직 불편하다면 스크립팅이나 Services Workers같이 많은 기능들을 버전 2에서 사용할 수 있다는 걸 알아 두세요 이제 올해 업데이트된 API를 살펴보겠습니다 Declarative Net Request부터 시작하죠 Declarative Net Request는 콘텐츠 차단 API로 빠르게 개인 정보 보호를 제공하는 웹 확장 프로그램을 제공하는데 규칙 집합으로 네트워크 요청을 차단하거나 변경합니다 여러분이 이 API를 사용하면 요청을 막고 변경하는 모든 작업을 Safari에 위임할 수 있으며 여러분은 적용해야 하는 콘텐츠 차단 규칙만 정하면 됩니다 여러분이 Manifest에서 규칙 집합을 지정할 수 있습니다
저는 Declarative Net Request 권한을 추가하고 declarative_net_request 키를 사용해서 모든 페이지에 적용해야 하는 규칙 집합을 하나 추가했습니다 전에는 Manifest에서 규칙 집합을 10개까지 선언할 수 있었습니다 하지만 지금은 이 기능을 새로 업데이트해서 규칙 집합을 50개까지 선언할 수 있습니다 여러분의 확장 프로그램을 더 여러분 마음대로 바꾸는 거죠 하지만 그중 10개 규칙 집합만 한 번에 적용할 수 있습니다 규칙 집합 만드는 방법에 대한 자세한 설명은 Safari 웹 확장 프로그램 관련 작년 프레젠테이션을 확인하세요 API에 대해 더 깊이 알 수 있습니다 Declarative Net Request의 몇 가지 새로운 기능을 알아보죠 전에는 Manifest에서만 규칙 집합을 선언할 수 있었지만 지금은 다음의 두 가지 API를 구현해 여러분의 규칙을 활발하게 업데이트할 수 있게 해 줍니다 첫 API는 updateSessionRules입니다 여러분의 확장 프로그램에서 규칙을 추가하거나 제거할 수 있죠 하지만 브라우저 세션이나 확장 프로그램 업데이트에서 이런 규칙이 유지되지 않는단 걸 알아두셔야 합니다 계속 유지되는 규칙을 업데이트하고 싶다면 updateDynamicRules API를 사용합니다 이는 모든 확장 프로그램을 업데이트하지 않고도 차단된 규칙을 업데이트할 수 있게 해 줍니다 이제 이 API 중 하나를 사용해서 저희 규칙 집합을 수정하는 법을 알아보죠 제가 Sea Creator 확장 프로그램을 사용해 웹 페이지의 일부 콘텐츠를 차단할 겁니다 그리고 새로운 API를 이용해 선택 페이지의 콘텐츠 차단을 해제합니다 Manifest 확장 프로그램에서 가장 먼저 실행할 건 Declarative Net Request를 추가하는 겁니다
그다음 Declarative Net Request 키로 규칙 집합을 추가합니다
적용된 규칙은 rules.json 파일에 있습니다
이 파일에서는 모든 URL의 이미지를 차단하는 하나의 규칙을 선언했습니다 이제 확장 프로그램을 구축하고 Safari에서 어떻게 적용되나 보죠
보시는 것처럼 이 페이지의 이미지가 사라졌습니다 저희가 기대했던 그대로죠 콘텐츠 차단 규칙이 Safari에 성공적으로 적용됐다는 뜻이죠 물고기를 검색한 위키피디아 페이지로 이동해서 이 사이트의 이미지도 차단됐는지 확인해 봅니다 모든 페이지의 이미지를 차단하게 규칙을 업데이트해 볼게요 webkit.org 블로그 페이지만 빼고요
Declarative Net Request를 위해 업데이트한 API를 이용해 그 규칙을 실행할 수 있습니다
Xcode로 돌아가서 몇 가지 바꿔 보도록 하죠 popup.js 파일에서 콘텐츠 차단 규칙을 업데이트하는 함수를 선언할 겁니다
webkit.org/blog-files pages에서 이미지 허용 규칙을 설정하고 updateSessionRules API를 사용해 이 규칙을 규칙 집합에 추가합니다 마지막으로 확장 프로그램을 구축해 Safari에서 변경 사항을 실험합니다
보시다시피 이 블로그 글에 이미지가 로딩됐다는 건 이 사이트에서 이미지를 허용하는 새 규칙이 효과가 있다는 뜻이죠 위키피디아 사이트에 접속해 보면 이 페이지의 이미지는 여전히 차단된 걸 확인할 수 있습니다 새 규칙이 이 페이지에는 적용되지 않았다는 거죠 Declarative Net Request API를 이런 식으로 사용해서 콘텐츠 차단 규칙을 업데이트하면 됩니다
이제 여러분의 확장 프로그램이 웹 페이지와 어떻게 통신하는지 알아보죠 웹 사이트에서 확장 프로그램을 사용하도록 설정해 놓은 경우에는 이 기능을 통해 지정 동작을 만들 수 있습니다 API는 externally_connectable로 표시합니다
이걸 사용하기 위해 Manifest에 일치하는 패턴을 선언합니다 일치하는 패턴은 확장 프로그램과 통신할 페이지를 결정하죠
그리고 중요한 건 브라우저 네임스페이스를 써야만 이 기능이 작용한다는 겁니다 마지막으로 사용자가 메시지를 보내거나 받기 전에 페이지에 대한 확장 프로그램 접근 권한을 부여해야 합니다
이 기능을 사용하기 위해 페이지에 추가할 코드를 살펴보죠 우선, extensionID가 필요합니다 확장 프로그램의 번들 식별자와 이 포맷의 팀 식별자입니다 developer.apple.com에서 팀 식별자를 찾을 수 있습니다 여러분의 계정 설정에 있는 멤버십 탭에 있죠 그다음 Send Message API를 이용해 확장 프로그램에 메시지를 게시합니다
확장 프로그램이 받을 응답을 함수를 통해 처리할 수 있습니다
이제 메시지 수신을 위해 확장 프로그램의 코드를 살펴보죠 여러분의 확장 프로그램은 onMessageExternal 이벤트를 통해 웹 페이지에서 메시지를 수신할 수 있습니다 확장 프로그램은 이벤트 리스너에 전달된 메서드를 사용해 메시지를 웹 페이지로 다시 보낼 수 있습니다
브라우저마다 확장 프로그램 웹 스토어가 다르기 때문에 확장 프로그램에는 여러 식별자가 있을 수 있습니다 그래서 올바른 사용법을 정해야 합니다 그래야 Chrome이나 Edge 확장 프로그램이 아니라 Safari 웹 확장 프로그램에 메시지를 보낼 수 있죠 여러분이 그렇게 하기 위해서는 browser.runtime.sendMessage API와 함께 Promise.all이란 요청을 사용하면 됩니다
다음으로는 이 작업 수행에 도움이 되는 코드를 살펴볼게요 여러분은 웹 페이지에서 여러 개의 확장 프로그램 ID로 여러 개의 메시지를 보낼 수 있습니다 정확히 하나의 확장 프로그램에서 하나의 응답만 받을 수 있고 그걸 통해 앞으로 통신에 쓸 확장 프로그램 ID를 알 수 있죠
determineExtensionID라는 함수가 있습니다 browser.runtime.sendMessage API를 이용해 이 함수가 확장 프로그램에 메시지를 보내죠
여러분의 ID가 여러 개라서 올바른 ID를 사용하고 싶은 경우에는 Promise.all을 사용해서 determineExtensionID를 사용하는 요청을 여러 번 할 수 있습니다 Promise.all은 프로미스 집합체가 여러 개의 가치값을 가진 하나의 프로미스로 모입니다
여러분은 배열을 이용해서 사용자가 설치한 확장 프로그램을 찾을 수 있습니다 확장 프로그램의 백그라운드 페이지에서 웹 페이지의 메시지를 기다려야 합니다 메시지를 받으면 메시지를 다시 보내서 확장 프로그램이 설치된 걸 웹 페이지에 알려야 합니다 이렇게 새로운 externally_connectable API로 확장 프로그램이 웹 페이지와 통신할 수 있도록 하는 겁니다 저희가 업데이트한 다음 기능은 개인적으로 좋아하는 부분인데요 바로 unlimitedStorage입니다 정말 기쁘게도 unlimitedStorage가 완전히 무제한이 됐습니다 이는 여러분의 많은 요청을 받은 기능으로 확장 프로그램에 할당되는 10MB 제한이 없어졌다는 겁니다 필요하다고 생각하는 만큼 데이터를 자유롭게 쓸 수 있죠 하지만 중요한 건 사용자가 프로그램에서 사용하는 데이터를 언제든 지울 수 있단 겁니다 그러니 꼭 필요한 데이터만 저장해야 합니다 사용자가 데이터를 삭제하지 않도록 말이죠 이 기능을 사용하려면 Manifest에서 storage와 unlimitedStorage 권한만 주장하면 됩니다
지금까지 말씀드린 게 저희가 작년에 웹 확장 프로그램을 위해 업데이트한 API였습니다 마지막으로 새로운 기능에 대해 얘기해 보죠 이를 통해 사용자가 모든 기기에서 여러분의 확장 프로그램을 쉽게 사용할 수 있습니다 Safari 16에서 확장 프로그램을 더 매끄럽게 사용할 수 있습니다 사용자의 기기 중 하나에서 확장 프로그램을 실행하면 다른 여러 기기에서도 실행이 되는 겁니다 그것 외에도 확장 프로그램을 다운로드하는 과정도 훨씬 간단하게 만들었습니다 어떻게 실행되는지 한번 보시죠 사용자가 Mac에서 확장 프로그램 중 하나를 사용하도록 설정했다고 가정해 볼게요 다른 기기의 확장 프로그램 설정에서 확장 프로그램을 다운할 수 있는 옵션이 있습니다 프로그램을 다운받으면 기기에서 자동으로 실행되고 사용자 경험을 향상시켜 주는 거죠
이제 웹 확장 프로그램과 콘텐츠 차단 기능에서 이 기능을 어떻게 쓰는지 알아보겠습니다 우선, 여러분이 App Store에 확장 프로그램을 제출할 때 iOS와 iPadOS, macOS를 위한 프로그램을 나열하는 게 좋습니다 이러면 사용자가 모든 장치에서 확장 프로그램을 사용할 수 있죠
그다음 기간 확장 프로그램을 동기화하기 위해서 다음의 두 방법 중 하나를 사용해야 합니다 가장 간단하면서 저희가 권장하는 방법은 범용 구매 방식을 채택하는 겁니다
사용자는 범용 구매를 통해 확장 프로그램을 모든 플랫폼에서 즐길 수 있죠 단 한 번의 구매로요 이 방법을 사용한다면 준비는 다 끝난 겁니다 확장 프로그램을 한 번만 받으면 제가 보여 드린 모든 기능을 사용자가 접할 수 있는 거죠
범용 구매를 설정하려면 여러분의 확장 프로그램에 단일 번들 식별자를 써야 합니다 그래야 App Store Connect에서 같은 앱 기록으로 연결됩니다
더 자세한 방법이 궁금하시면 '확장 프로그램에 대한 범용 구매 설정 방법' 자료를 확인해 보세요 하지만 범용 구매를 설정하지 않기로 한 경우에도 수동으로 앱을 연결할 수 있습니다 이렇게 하려면 동기화하고자 하는 앱과 확장 프로그램에서 Xcode를 사용해 plist에 번들 식별자를 추가해야 합니다 iOS 앱과 확장 프로그램을 macOS와 동기화하려면 plist에서 특정 키를 사용해야 합니다 이 키를 macOS 앱 plist에 넣으면 macOS 확장 프로그램 plist에도 넣는 겁니다 macOS 앱을 동기화할 때도 동일한 프로세스를 따릅니다 iOS 앱 plist에 이 키를 추가하면
iOS 확장 프로그램 plist에도 추가합니다 이제 Xcode에서는 어떻게 작동하는지 보죠 Xcode에서 가장 먼저 할 일은 각 타깃에 대한 설정을 업데이트하는 겁니다 동기화하고자 하는 확장 프로그램과 앱에 번들 식별자를 포함시키는 거죠 우선 해당 macOS 앱의 번들 식별자를 iOS 앱의 info plist에 추가하겠습니다
보시다시피 macOS 앱에서 iOS 앱 번들 식별자를 추가해 동일한 프로세스를 실행했습니다 그리고 마찬가지로 iOS 확장 프로그램에도 macOS 확장 프로그램 번들 식별자를 추가합니다 마지막으로 macOS 확장 프로그램에 iOS 확장 프로그램 번들 식별자를 추가합니다 앱과 확장 프로그램을 이렇게 쉽게 연결해서 사용자가 어디서나 사용할 수 있도록 하는 거죠 요약하자면, 사용자가 이 기능을 사용하도록 설정할 수 있는데 여러분이 범용 구매를 설정하거나 Xcode에서 iOS와 macOS 앱과 확장 프로그램에 번들 식별자를 추가하면 됩니다 저희는 오늘 Manifest 버전 3와 업데이트된 API 여러 기기에서 확장 프로그램을 동기화하는 법을 알아봤습니다 Safari 웹 확장 프로그램의 새로운 기능들에 대해 여러분도 저만큼 기대해 주시면 좋겠습니다 오늘 사용한 코드가 포함된 샘플을 자유롭게 다운받아서 저희가 소개한 API를 실험해 보세요
저희는 여러분의 의견을 기다립니다 피드백 지원을 통해 버그를 보고하거나 Safari 개발자 포럼에 와서 얘기하셔도 됩니다 저희가 더 나은 확장 프로그램을 만들 수 있도록 얘기해 주세요 저희는 진심으로 여러분의 생각을 알고 싶습니다 웹 확장 프로그램 커뮤니티 그룹에 가입하는 것도 웹 확장 프로그램의 미래 형성에 도움이 될 겁니다 Web Inspector 확장 프로그램 생성에 대한 WWDC 프레젠테이션도 확인해 보세요 시청해 주셔서 감사합니다 남은 WWDC 기간도 즐겁게 보내세요
-
-
2:43 - Executing script on webpages
// Manifest version 2 browser.tabs.executeScript(1, { frameId: 1, code: "document.body.style.background = 'blue';" });
-
3:00 - scripting.executeScript API
// Manifest version 3 function changeBackgroundColor(color) { document.body.style.background = color; }; browser.scripting.executeScript({ target: { tabId: 1, frameIds: [ 1 ] }, func: changeBackgroundColor, args: [ "blue" ] });
-
4:02 - tabs.executeScript file
// Manifest version 2 browser.tabs.executeScript({ 1, file: "file.js" });
-
4:09 - scripting.executeScript API files
// Manifest version 3 browser.scripting.executeScript({ target: { tabId: 1 }, files: [ "file.js", "file2.js" ] });
-
4:15 - scripting.insertCSS
// Add styling browser.scripting.insertCSS({ target: { tabId: 1, frameIds: [ 1, 2, 3 ] }, files: [ "file.css", "file2.css" ] });
-
4:21 - scripting.removeCSS
// Remove styling browser.scripting.removeCSS({ target: { tabId: 1, frameIds: [ 1, 2, 3 ] }, files: [ "file.css", "file2.css" ] });
-
5:08 - Manifest version 3 web_accessible_resources
// Manifest version 3 "web_accessible_resources": [ { "resources": [ "pie.png" ], "matches": [ "*://*.apple.com/*" ] }, { "resources": [ "cookie.png" ], "matches": [ "*://*.webkit.org/*" ] } ]
-
5:42 - Manifest version 3 action
// Manifest version 3 "action": { "default_icon": { "16": "Images/icon16.png" }, "default_title": "defaultTitle" }
-
5:57 - Manifest version 2 content_security_policy
// Manifest version 2 "content_security_policy" : "script-src 'unsafe-eval' https://*apple.com 'self'"
-
6:08 - Manifest version 3 content_security_policy
// Manifest version 3 "content_security_policy" : { "extension_pages" : "script-src 'unsafe-eval' 'self'" }
-
10:31 - Specifying a ruleset
// manifest.json "permissions": [ "declarativeNetRequest" ], "declarative_net_request": { "rule_resources": [ { "id": "my_ruleset", "enabled": true, "path": "rules.json" } ] }
-
11:44 - updateSessionRules
// Rules that won't persist browser.declarativeNetRequest.updateSessionRules({ addRules: [ rule ] }); // Rules that will persist browser.declarativeNetRequest.updateDynamicRules({ addRules: [ rule ] });
-
14:33 - externally connectable
// In the webpage let extensionID = "com.apple.Sea-Creator.Extension (GJT7Q2TVD9)"; browser.runtime.sendMessage(extensionID, { greeting: "Hello!" }, function(response) { console.log("Received response from the background page:"); console.log(response.farewell); });
-
15:00 - Message from webpage to extension (in the webpage)
// In the webpage let extensionID = "com.apple.Sea-Creator.Extension (GJT7Q2TVD9)"; browser.runtime.sendMessage(extensionID, { greeting: "Hello!" }, function(response) { console.log("Received response from the background page:"); console.log(response.farewell); });
-
15:33 - Message from webpage to extension (in the background page)
// In the background page browser.runtime.onMessageExternal.addListener(function(message, sender, sendResponse) { console.log("Received message from the sender:"); console.log(message.greeting); sendResponse({ farewell: "Goodbye!" }); });
-
16:17 - Determining the correct identifier
// Determining the correct identifier function determineExtensionID(extensionID) { return new Promise((resolve) => { try { browser.runtime.sendMessage(extensionID, { action: 'determineID' }, function(response) { if (response) resolve({ extensionID: extensionID, isInstalled: true, response: response }); else resolve({ extensionID: extensionID, isInstalled: false }); }); } }); };
-
17:09 - background.js
// background.js browser.runtime.onMessageExternal.addListener(function(message, sender, sendResponse) { if (message.action == "determineID") { sendResponse({ "Installed" }); } });
-
18:07 - Unlimited storage
// manifest.json "permissions": [ "storage", "unlimitedStorage" ]
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.