DY N DY
Chrome Extension - Content Scripts (번역) 본문
https://developer.chrome.com/extensions/content_scripts
표 아래로는 아직 정리를 안함....
ContentScripts
Content script는 웹페이지의 context에서 실행되는 JavaScript 파일이다.
표준 Document Object Model(DOM)을 사용해서 content script는 브라우저로 방문하는 웹페이지의 내용을 읽거나 변경할 수 있다.
Content script로 가능한 몇 가지 예시
l 웹페이지에연결되지 않은 URL을 검색하고 하이퍼링크로 변환
l 텍스트를더 읽기 쉽게 만들기 위해 글꼴 크기를 증가
l DOM에서 microformat data를 찾고 처리
하지만 content script는 몇 가지 제한이 있다.
l Chrome.* API 사용 (아래 제외)
n extension(getURL, inlncognitoCOntext, lastError, onRequest,sendRequest_
n i18n
n runtime(connect, getManifest, getURL, id, onConnect, onMessage,sendMessage)
n storage
l 익스텐션페이지에정의된 변수나 함수 사용
l 웹페이지나다른 content script에 정의된 변수나 함수 사용
이 제한사항은 생각보다 나쁘지는 않다. Content script는간접적으로 chrome.* API를 사용할 수 있다. 부모익스텐션과 메시지를 교환하여 익스텐션 데이터에 접근하고, 익스텐션 액션도 요청할 수 있다.
Content script들은 그들의 부모 익스텐션으로 cross-site XMLHttpRequests를 가능하게 한다. 그리고그들은 공유된 DOM을 통해 웹페이지 간에 통신을 가능하게 한다.
더 많은 content script의 기능들을 알고 싶다면 아래의execution environment를 공부할 것
https://developer.chrome.com/extensions/content_scripts#execution-environment
.
Manifest
만약 content script 코드를 항상 주입하고 싶다면 익스텐션 manifest에 content script 필드를 이용하여 등록하면된다. 예제는 아래와 같다.
{ |
"name": "My extension", |
... |
"content_scripts": [ |
{ |
"matches":["http://www.google.com/*"], |
"css": ["mystyles.css"], |
"js": ["jquery.js", "myscript.js"] |
} |
], |
... |
} |
코드를 가끔식 필요할 때만 삽입할 경우 Programmaticinjection에 설명된 대로 permissions 필드를 사용하면 된다.
{ |
"name": "My extension", |
... |
"permissions": [ |
"tabs", "http://www.google.com/*" |
], |
... |
} |
Content script 필드를 사용하여 익스텐션은 여러 content script를 페이지에 삽입이 가능하다.
이 content script는 여러 JavaScript와 css 파일들을 가질 수 있다.
Content script배열의 항목에는 다음과 같은 속성을 가질수 있다.
Name | Type | Description |
matches | array of strings | 필수, 이 content script가 주입될 페이지를 지정. 더 많은 문법등의 정보를 확인하고 싶다면 Match Patterns 페이지를 확인할 것. URL을 제외하고 싶다면 Match patterns and globs를 확인할 것 |
exclude_matches | array of strings | 선택, 제외될 페이지를 주입한다. 나머지 정보는 위와 같다 |
match_about_blank | boolean | 선택, about:blank, about:srcdoc의 내용에 스크립트를 삽입할지 지정,
기본값은 false |
css | array of strings | 선택, CSS파일 리스트는 일치하는 페이지로 주입된다. 어떤 DOM이 생성되거나 페이지에 보여지기 전에 css가 배열에 나타나는 순서에 주입된다. |
js | array of strings | 선택, JavaScript 파일 리스트는 일치하는 페이지로 주입된다. 배열에 나타나는 순서대로 주입된다. |
run_at | string | 선택, js안에 있는 파일들이 주입되는 경우 컨트롤 한다. “document_start”, “document_end”, 또는 “document_idle”일 수 있다. 기본값은 “document_idle”이다.
“document_start”인 경우 파일들은 css파일이 주입된 후에 주입된다.그러나 다른 DOM이 생성되거나 다른 스크립트들이 실행되기 전에 주입된다.
“document_end”인 경우 파일들은 DOM이 완료된 후 바로 주입된다.그러나 이미지, 프레임과 같은 다른 subresource들이 로드되기 전에 주입된다.
“document_idle”인 경우 브라우저는“document_end”와window.onload이벤트 직후 사이의 시간을 선택하여 파일을 주입한다.정확한 주입순간은 문서가 얼마나 복잡한지, 페이지 로드 시간이 얼마나 긴지, 페이로드 속도를 위해 최적화되어 있다.
NOTE: “document_idle”인 경우 content script는 항상 window.onload이벤트를 받을 필요는 없다. Window.onload이벤트를 수신하는 것은DOM이 완료된 후에 실행되는 것이 보장되기 때문에 “document_idle”로 실행되는 content_script에게는 필요가 없다. 만약 스크립트다 무조건 window.onload후에 실행되어야 한다고 하면document.readyState property를 사용해 onload가 실행되었는지 확인 가능하다.
|
all_frames | boolean | 선택, content script가 일치하는 페이지 또는 오직 top frame에서content script를 실행한다. 기본값은 false, 이것은 top frame만 일치하는 것을 뜻한다. |
include_globs | array of strings | 선택, glob과 매칭되는 URL만을 매칭 후 적용, @include키워드(그리스몽키키워드)를 사용해서 실험하도록 되어 있다. 아래의 Match patterns and globs를 참조할 것 |
exclude_globs | array of strings | 선택, 위와 반대, 일치하는 URL을 제외 후 적용 @exclude키워드 사용,나머지 설명은 위와 동일
|
Matchpatterns and globs
Content script는 만약 URL이어떤 매치 패턴이나 어떤 glob 패턴에 들어있다면(URL이매치되지 않았거나 exclude패턴으로 매치된게 아니라면) 페이지에주입될 것이다.
만약 익스클루드_매치가 ["*://*/*business*"]면 콘텐트스크립트는 아마"http://www.nytimes.com/health" 인젝트할거지만"http://www.nytimes.com/business".는 안인젝트할것이다. |
만약에 인클루드 글롭스가 ["*nytimes.com/???s/*"]면 콘텐트스크립트는 아마"http:/www.nytimes.com/arts/index.html" and "http://www.nytimes.com/jobs/index.html" but not into "http://www.nytimes.com/sports/index.html". 이럴것.. |
만약 익스클루드 글롭스가 ["*science*"]면 콘텐트스크립트는"http://www.nytimes.com" but not into "http://science.nytimes.com" or "http://www.nytimes.com/science". 이럴거다 |
Glob 속성은 더 유연하다. Glob는 * ? 이런 것들을 사용가능하다. 별표는 빈문자열을 포함한 길의의 문자열과 일치. 물음표는 단일문자 |
예를들어서 "http://???.example.com/foo/*"는 아래랑 일치 |
http://www.example.com/foo/bar |
http://the.example.com/foo/ |
이 아래랑은 불일치 |
http://my.example.com/foo/bar |
http://example.com/foo/ |
http://www.example.com/foo |
프로그래매틱 인젝션 |
코드를 프로그램적으로 페이지에 주입하는것은 너가 자스나 씨에스코드를 패턴과 일치하는 모든 단일 페이지에 주입할필요없을 경우 유용함. 예를들어사용자가 브라우저의 액션아이콘을 클릭할 때만 스크립트 실행 |
코드를 페이지에 삽입하려면 익스텐션은 페이지에 오리진 간 권한이 있어야 함. 이것은 또한 chrome.tabs모듈을 사용할 수 있어야 함. 또한 매니페스트 파일의 권한필드를 사용하여 두가지 퍼미션을 얻을 수 있다 |
사용자 권한설정이 되면 tabs.executeScript를 호출하여 페이지에 자스를 삽입할수있음. |
make_page_red예제의 다음 코드는 현재 탭의 페이지에 자바스크립트를 삽입하고 실행하여 사용자 클릭에 반응함 |
chrome.browserAction.onClicked.addListener(function(tab) { |
chrome.tabs.executeScript({ |
code: 'document.body.style.backgroundColor="red"' |
}); |
}); |
permissions: [ |
"activeTab" |
], |
브라우저가 HTTP페이지를 표시하고 사용자는 익스텐션의 브라우저 버튼을 클릭하면 익스텐션의 백그라운드칼라는 적색으로 바뀜(속성바꿈) 결과적으로 아무튼 레드로바꿈 |
일반적으로 이전 샘플코드같이 직접 코드를 삽입, 파일에 코드를 삽입, 파일의 콘텐츠는 다음과 같음 |
chrome.tabs.executeScript(null, {file: "content_script.js"}); |
Execution environment |
실행 환경 |
콘텐츠 스크립트는 틀별한 환경(고립된 세계?)에서 실행함. |
콘텐츠스크립트는 그들이 인젝션된 페이지의 돔에 엑세스하지만 어떤 자바스크립트 변수나 함수도 페이지에서 만들어지지는 않음. |
이거는 콘텐츠스크립트가 페이지가 실행될때 다른 실행되는 자바스크립트가 없는 것 같아 보이겟지만 반대와 같다. |
자바스크립트는 콘텐츠스크립트에 정의된 어떤 변수나 함수를 콜하거나 엑세스하지 못하는 페이지에서 실행된다. |
그니까 콘텐츠스크립트에서 정의된건 못쓰는데 다른 자바스크립트가 실행이 안되는것은 아니라는것 같음.. |
예) |
<html> |
자 이 콘텐츠 스크립트가 hello.html에 인젝션된다고 가정하자 |
var greeting = "hola, "; |
var button = document.getElementById("mybutton"); |
button.person_name = "Roberto"; |
button.addEventListener("click", function() { |
alert(greeting + button.person_name + "."); |
}, false); |
버튼을 누르면 두 인사말을 모두 볼 수 있다. |
고립된세계(isolated worlds)는 각각의 컨텐츠스크립트가 자바스크립트 환경을 페이지나 다른 콘텐트스크립트의 충돌을 걱정하지 않고 바꿀수있도록 허락한다. |
예를들어 콘텐트스크립트는 Jquery v1을 포함할수있고, 페이지는 Jquery v2를 포함할 수 있다. 이것들은 서로 출돌하지 않을 것이다. |
다른 중요한 이점은 완전히 페이지의 자바스크립트가 익스텐션의 자바스크립트와 분리된다는 것이다. |
이것은 우리에게 추가적인 기능을 그거를 엑세스하는 웹페이지에 대한 걱정없이 웹페이지에서 엑세스 불가능한 콘텐츠 스크립트에 제공할수가 있다. |
페이지 와 익스텐션에 의해 공유되는 자바스크립트 객체가 무슨일이 생겼는지 주목할필요가없다 |
예를들어 윈도우 온로드이벤트같은거 |
각각의 고립된 세계는 객체의 자체 버전을 본다? |
객체에 할당을 하면 당신의 독립적인 객체의 복사본에도 영향을 미친다. |
예를들어 페이지와 익스텐션 모두 윈도우온로드함수를 할당해주면 어느 하나의 이벤트핸들러도 읽을 수 없다. |
이벤트핸들러는 할당된 순서대로 호출된다. |
embed된 페이지와의 커뮤니케이션 |
콘텐츠스크립트 익스텐션환경과 호스트된페이지가 서로 고립이되어있지만 그들은 페이지의 DOM 엑세스를 공유한다. |
페이지 콘텐츠 스크립트와 통신하고자 하는 경우 (또는 컨텐츠스크립트를 통해 익스텐션을) 공유된 DOM을 통해야 하낟. |
윈도우점포스트메시지를 이용하여 가능한 제예(또는 윈도우점 웹킷포스트메시지 -전송객체) |
var port = chrome.runtime.connect(); |
window.addEventListener("message", function(event) { |
// We only accept messages from ourselves |
if (event.source != window) |
return; |
if (event.data.type && (event.data.type == "FROM_PAGE")) { |
console.log("Content script received: " + event.data.text); |
port.postMessage(event.data.text); |
} |
}, false); |
document.getElementById("theButton").addEventListener("click", |
function() { |
window.postMessage({ type: "FROM_PAGE", text: "Hello from the webpage!" }, "*"); |
}, false); |
위의 예에서 example.html(익스텐션의 일부가 아님)은 자체 포스트메시지인데 이 포스트페시지는 콘텐츠스크립트에 의해 인터셉트되고 검사된 포스트메시지고 그담에 익스텐션 프로세스에 포스트된다. |
이런 방식으로 페이지는 익스텐션 프로세스에 통신회선을 만든다. |
반대도 유사한 방법을 통해 가능하다. |
보안 고려 사항 |
콘텐츠 스크립트를 작성할 때 두가지 보안문제에 대해 알고있어야 한다. |
첫째로 콘텐츠 스크립트에 주입된 웹사이트의 보안 취약점을 소개하지 않도록 주의할 것 |
(예를들어 XMLHttpRequest객체를 만듦으로서) |
다른 웹사이트로부터 컨텐츠를 수신하는 경우 예를들어 현재 페이지에 콘텐츠를 주입하기 전에 사이트 간 스크립트 공격에 대한 컨텐츠를 필터링하도록 주의할 것 |
예를들어 innerText보다는 innerHTML을 통해 컨텐츠를 주입하는 것을 선호함. |
Http 콘텐츠가 네트워크에 의해 손상되었을 수 있기 떄문에 Https페이지에서Http콘텐츠를 검색할 떄 특히 주의해야 man-in-the-middle??? 사용자가 적대적 네트워크게있는경우???? |
둘째로 격리된 세계에서 콘텐츠스크립트를 실행하는 웹페이지에서 몇 가지 보호 기능을 제공하지만 악의적인 웹 페이지가 여전히 당신의 컨텐츠스크립트를 공격할수있다. 당신이 임의의 웹 페이지에서 컨텐츠를 사용하는 경우 |
예를 들어 아래 패턴이 위험함 |
var data = document.getElementById("json-data") |
// WARNING! Might be evaluating an evil script! |
var parsed = eval("(" + data + ")") |
var elmt_id = ... |
// WARNING! elmt_id might be "); ... evil script ... //"! |
window.setTimeout("animate(" + elmt_id + ")", 200); |
대신에 스크립트를 실행하지 않는 안전한 API를 선호 |
var data = document.getElementById("json-data") |
// JSON.parse does not evaluate the attacker's scripts. |
var parsed = JSON.parse(data); |
var elmt_id = ... |
// The closure form of setTimeout does not evaluate scripts. |
window.setTimeout(function() { |
animate(elmt_id); |
}, 200); |
익스텐션 파일에 |
chrome.extension.getURL을 이용해서 확장파일의 URL을 얻을수있다. URL결과를 사용할수있다 다음 코드를 보자 |
//Code for displaying <extensionDir>/images/myimage.png: |
var imgURL = chrome.extension.getURL("images/myimage.png"); |
document.getElementById("someImage").src = imgURL; |
Examples |
콘텐츠 스크립트를 사용하는 많은 예를 찾을 수 있다. |
메시지 타이머 등등등 |
콘텐츠스크립트 비디오 |
소스 흩어보기 |
'PARK > IT관련' 카테고리의 다른 글
우분투 GUI 부팅 (0) | 2016.10.13 |
---|---|
VIM(VI)단축키 (0) | 2016.08.26 |
Chrome Extension - Event Page (번역) (1) | 2016.06.16 |
Chrome Extension - Overview (번역) (0) | 2016.06.15 |
Native Message (Chrome) (0) | 2016.06.02 |