외부 콘텐츠

Chrome 앱 보안 모델은 iframe의 외부 콘텐츠 및 인라인 스크립팅 및 eval() 사용을 허용하지 않습니다. 이러한 제한사항을 재정의할 수 있지만 외부 콘텐츠는 앱에서 격리해야 합니다.

격리된 콘텐츠는 앱의 데이터나 API에 직접 액세스할 수 없습니다. 교차 출처 XMLHttpRequests 및 사후 메시지를 사용하여 이벤트 페이지와 샌드박스 콘텐츠 간에 통신하고 API에 간접적으로 액세스합니다.

외부 리소스 참조

앱에서 사용하는 콘텐츠 보안 정책은 많은 종류의 원격 URL을 사용하는 것을 허용하지 않으므로 앱 페이지에서 외부 이미지, 스타일시트, 글꼴을 직접 참조할 수 없습니다. 대신 교차 출처 XMLHttpRequests를 사용하여 이러한 리소스를 가져온 다음 blob: URL을 통해 제공할 수 있습니다.

매니페스트 요구사항

교차 출처 XMLHttpRequest를 실행하려면 원격 URL 호스트에 대한 권한을 추가해야 합니다.

"permissions": [
    "...",
    "https://supersweetdomainbutnotcspfriendly.com/"
  ]

교차 출처 XMLHttpRequest

원격 URL을 앱으로 가져오고 콘텐츠를 blob: URL로 제공합니다.

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://supersweetdomainbutnotcspfriendly.com/image.png', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
  var img = document.createElement('img');
  img.src = window.URL.createObjectURL(this.response);
  document.body.appendChild(img);
};

xhr.send();

이러한 리소스는 오프라인에서 사용할 수 있도록 로컬에 저장하는 것이 좋습니다.

외부 웹페이지 삽입

webview 태그를 사용하면 앱에 외부 웹 콘텐츠(예: 웹페이지)를 삽입할 수 있습니다. Chrome 앱 내에서 사용 중지된 원격 URL을 가리키는 iframe을 대체합니다. iframe과 달리 webview 태그는 별도의 프로세스에서 실행됩니다. 즉, 내부 악용은 여전히 격리되며 승격된 권한을 얻을 수 없습니다. 또한 저장소(쿠키 등)가 앱에서 격리되므로 웹 콘텐츠가 앱의 데이터에 액세스할 방법이 없습니다.

WebView 요소 추가

webview 요소는 소스 콘텐츠로 연결되는 URL을 포함하고 크기를 지정해야 합니다.

<webview src="http://news.google.com/" width="640" height="480"></webview>

숙박 시설 업데이트

webview 태그의 src, width, height 속성을 동적으로 변경하려면 JavaScript 객체에서 직접 속성을 설정하거나 setAttribute DOM 함수를 사용하면 됩니다.

document.querySelector('#mywebview').src =
    'http://blog.chromium.org/';
// or
document.querySelector('#mywebview').setAttribute(
    'src', 'http://blog.chromium.org/');

샌드박스 로컬 콘텐츠

샌드박스를 사용하면 지정된 페이지를 샌드박스 처리된 고유한 출처에 제공할 수 있습니다. 그러면 이러한 페이지는 콘텐츠 보안 정책에서 제외됩니다. 샌드박스 처리된 페이지에서는 iframe, 인라인 스크립팅, eval()를 사용할 수 있습니다. sandbox의 매니페스트 필드 설명을 확인하세요.

하지만 장단점이 있습니다. 샌드박스 처리된 페이지에서는 Chrome을 사용할 수 없습니다.* 배열됩니다 eval()와 같은 작업을 수행해야 하는 경우 CSP에서 제외되도록 이 경로로 이동하지만 멋진 새 기능은 사용할 수 없습니다.

샌드박스에서 인라인 스크립트 사용

다음은 인라인 스크립트와 eval()를 사용하는 샌드박스 환경의 샘플입니다.

<html>
  <body>
    <h1>Woot</h1>
    <script>
      eval('console.log(\'I am an eval-ed inline script.\')');
    </script>
  </body>
</html>

매니페스트에 샌드박스 포함

매니페스트에 sandbox 필드를 포함하고 샌드박스에 제공할 앱 페이지를 나열해야 합니다.

"sandbox": {
  "pages": ["sandboxed.html"]
}

창에서 샌드박스 페이지 열기

다른 앱 페이지와 마찬가지로 샌드박스 처리된 페이지가 열리는 창을 만들 수 있습니다. 다음은 샌드박스 처리되지 않은 기본 앱 창과 샌드박스 페이지를 위한 창, 이렇게 두 개의 창을 만드는 샘플입니다.

chrome.app.runtime.onLaunched.addListener(function() {
  chrome.app.window.create('window.html', {
    'bounds': {
      'width': 400,
      'height': 400,
      'left': 0,
      'top': 0
    }
  });

  chrome.app.window.create('sandboxed.html', {
    'bounds': {
      'width': 400,
      'height': 400,
      'left': 400,
      'top': 0
    }
  });
});

앱 페이지에 샌드박스 페이지 삽입

샌드박스 처리된 페이지는 iframe를 사용하여 다른 앱 페이지 내에 삽입할 수도 있습니다.

<!DOCTYPE html>
<html>
<head>
</head>
  <body>
    <p>I am normal app window.</p>

    <iframe src="sandboxed.html" width="300" height="200"></iframe>
  </body>
</html>

샌드박스 처리된 페이지에 메일 보내기

메시지 전송은 두 부분으로 구성됩니다. 발신자 페이지/창에서 메시지를 게시하고 수신 페이지/창에서 메시지를 수신 대기해야 합니다.

메시지 게시

postMessage를 사용하여 앱과 샌드박스 콘텐츠 간에 통신할 수 있습니다. 다음은 열리는 샌드박스 처리된 페이지에 메시지를 게시하는 백그라운드 스크립트 샘플입니다.

var myWin = null;

chrome.app.runtime.onLaunched.addListener(function() {
  chrome.app.window.create('sandboxed.html', {
    'bounds': {
      'width': 400,
      'height': 400
    }
  }, function(win) {
       myWin = win;
       myWin.contentWindow.postMessage('Just wanted to say hey.', '*');
     });
});

일반적으로 웹에서는 메일이 전송되는 정확한 출처를 지정하고 싶을 것입니다. Chrome 앱은 샌드박스 처리된 콘텐츠의 고유한 출처에 액세스할 수 없으므로 허용 가능한 출처 ('*')로 모든 출처만 허용 목록에 추가할 수 있습니다. 수신 쪽에서는 일반적으로 출처를 확인하고 싶지만 Chrome 앱 콘텐츠가 포함되어 있으므로 필수사항은 아닙니다. 자세한 내용은 window.postMessage를 참조하세요.

메시지를 듣고 답장하기

다음은 샌드박스 처리된 페이지에 추가되는 샘플 메시지 수신기입니다.

var messageHandler = function(event) {
  console.log('Background script says hello.', event.data);

  // Send a reply
  event.source.postMessage(
      {'reply': 'Sandbox received: ' + event.data}, event.origin);
};

window.addEventListener('message', messageHandler);

자세한 내용은 sandbox 샘플을 확인해 보세요.