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 샘플을 확인해 보세요.