DY N DY

Chrome Extension - Content Scripts (번역) 본문

PARK/IT관련

Chrome Extension - Content Scripts (번역)

손세지 2016. 6. 20. 10:56

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>
  <button id="mybutton">click me</button>
  <script>
    var greeting = "hello, ";
    var button = document.getElementById("mybutton");
    button.person_name = "Bob";
    button.addEventListener("click", function() {
      alert(greeting + button.person_name + ".");
    }, false);
  </script>
</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