Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / common / extensions / docs / templates / articles / app_external.html
blob4a13504ce5a4a35c316fb03a5627cc07472b035d
1 <h1>External Content</h1>
4 <p>
5 The <a href="app_architecture#security">Chrome Apps security model</a> disallows
6 external content in iframes and
7 the use of inline scripting and <code>eval()</code>.
8 You can override these restrictions,
9 but your external content must be isolated from the app.
10 </p>
12 <p>
13 Isolated content cannot directly
14 access the app's data or any of the APIs.
15 Use cross-origin XMLHttpRequests
16 and post-messaging to communicate between the event page and sandboxed content
17 and indirectly access the APIs.
18 </p>
20 <p class="note">
21 <b>API Sample: </b>
22 Want to play with the code?
23 Check out the
24 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/samples/sandbox">sandbox</a> sample.
25 </p>
27 <h2 id="external">Referencing external resources</h2>
29 <p>
30 The <a href="contentSecurityPolicy">Content Security Policy</a> used by apps disallows
31 the use of many kinds of remote URLs, so you can't directly reference external
32 images, stylesheets, or fonts from an app page. Instead, you can use use
33 cross-origin XMLHttpRequests to fetch these resources,
34 and then serve them via <code>blob:</code> URLs.
35 </p>
37 <h3 id="manifest">Manifest requirement</h3>
39 <p>
40 To be able to do cross-origin XMLHttpRequests, you'll need to add a permission
41 for the remote URL's host:
42 </p>
44 <pre data-filename="manifest.json">
45 "permissions": [
46 "...",
47 "https://supersweetdomainbutnotcspfriendly.com/"
49 </pre>
51 <h3 id="cross-origin">Cross-origin XMLHttpRequest</h3>
53 <p>
54 Fetch the remote URL into the app and serve its contents as a <code>blob:</code>
55 URL:
56 </p>
58 <pre>
59 var xhr = new XMLHttpRequest();
60 xhr.open('GET', 'https://supersweetdomainbutnotcspfriendly.com/image.png', true);
61 xhr.responseType = 'blob';
62 xhr.onload = function(e) {
63 var img = document.createElement('img');
64 img.src = window.URL.createObjectURL(this.response);
65 document.body.appendChild(img);
68 xhr.send();
69 </pre>
71 <p>You may want to <a href="offline_apps#saving-locally">save</a>
72 these resources locally, so that they are available offline.</p>
74 <h2 id="webview">Embed external web pages</h2>
76 <p class="note">
77 <b>API Sample: </b>
78 Want to play with the code? Check out the
79 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/samples/webview-samples/browser">browser</a>
80 sample.
81 </p>
83 <p>
84 The <a href="webview_tag"><code>webview</code></a> tag allows you to embed external web content in your
85 app, for example, a web page. It replaces iframes that point to remote URLs,
86 which are disabled inside Chrome Apps. Unlike iframes, the
87 <code>webview</code> tag runs in a separate process. This means that an exploit
88 inside of it will still be isolated and won't be able to gain elevated
89 privileges. Further, since its storage (cookies, etc.) is isolated from the app,
90 there is no way for the web content to access any of the app's data.
91 </p>
93 <h3 id="webview_element">Add webview element</h3>
95 <p>
96 Your <code>webview</code> element must include the URL to the source content
97 and specify its dimensions.
98 </p>
100 <pre data-filename="browser.html">
101 &lt;webview src="http://news.google.com/" width="640" height="480">&lt;/webview>
102 </pre>
104 <h3 id="properties">Update properties</h3>
107 To dynamically change the <code>src</code>, <code>width</code> and
108 <code>height</code> properties of a <code>webview</code> tag, you can either
109 set those properties directly on the JavaScript object, or use the
110 <code>setAttribute</code> DOM function.
111 </p>
113 <pre data-filename="browser.js">
114 document.querySelector('#mywebview').src =
115 'http://blog.chromium.org/';
116 // or
117 document.querySelector('#mywebview').setAttribute(
118 'src', 'http://blog.chromium.org/');
119 </pre>
121 <h2 id="sandboxing">Sandbox local content</h2>
124 Sandboxing allows specified pages
125 to be served in a sandboxed, unique origin.
126 These pages are then exempt from their Content Security Policy.
127 Sandboxed pages can use iframes, inline scripting,
128 and <code>eval()</code>.
129 Check out the manifest field description for
130 <a href="manifest/sandbox">sandbox</a>.
131 </p>
134 It's a trade-off though:
135 sandboxed pages can't use the chrome.* APIs.
136 If you need to do things like <code>eval()</code>,
137 go this route to be exempt from CSP,
138 but you won't be able to use the cool new stuff.
139 </p>
141 <h3 id="inline_scripts">Use inline scripts in sandbox</h3>
144 Here's a sample sandboxed page which uses an inline script and <code>eval()</code>:
145 </p>
147 <pre data-filename="sandboxed.html">
148 &lt;html>
149 &lt;body>
150 &lt;h1>Woot&lt;/h1>
151 &lt;script>
152 eval('console.log(\'I am an eval-ed inline script.\')');
153 &lt;/script>
154 &lt;/body>
155 &lt;/html>
156 </pre>
158 <h3 id="include_sandbox">Include sandbox in manifest</h3>
161 You need to include the <code>sandbox</code> field in the manifest
162 and list the app pages to be served in a sandbox:
163 </p>
165 <pre data-filename="manifest.json">
166 "sandbox": {
167 "pages": ["sandboxed.html"]
169 </pre>
171 <h3 id="opening_sandbox">Opening a sandboxed page in a window</h3>
174 Just like any other app pages,
175 you can create a window that the sandboxed page opens in.
176 Here's a sample that creates two windows,
177 one for the main app window that isn't sandboxed,
178 and one for the sandboxed page:
179 </p>
181 <p class="note">
182 NOTE:
183 A sandboxed window will not have access to the chrome.app APIs. If a
184 callback is provided to app.window.create it will be run, but will not have
185 the sandboxed window provided to it.
186 </p>
188 <pre data-filename="background.js">
189 chrome.app.runtime.onLaunched.addListener(function() {
190 chrome.app.window.create('window.html', {
191 'bounds': {
192 'width': 400,
193 'height': 400,
194 'left': 0,
195 'top': 0
199 chrome.app.window.create('sandboxed.html', {
200 'bounds': {
201 'width': 400,
202 'height': 400,
203 'left': 400,
204 'top': 0
208 </pre>
210 <h3 id="embedding_sandbox">Embedding a sandboxed page in an app page</h3>
212 <p>Sandboxed pages can also be embedded within another app page
213 using an <code>iframe</code>:</p>
215 <pre data-filename="window.html">
216 &lt;!DOCTYPE html>
217 &lt;html>
218 &lt;head>
219 &lt;/head>
220 &lt;body>
221 &lt;p>I am normal app window.&lt;/p>
223 &lt;iframe src="sandboxed.html" width="300" height="200">&lt;/iframe>
224 &lt;/body>
225 &lt;/html>
226 </pre>
229 <h2 id="postMessage">Sending messages to sandboxed pages</h2>
232 There are two parts to sending a message:
233 you need to post a message from the sender page/window,
234 and listen for messages on the receiving page/window.
235 </p>
237 <h3 id="post_message">Post message</h3>
240 You can use <code>postMessage</code> to communicate
241 between your app and sandboxed content.
242 Here's a sample background script
243 that posts a message to the sandboxed page it
244 opens:
245 </p>
247 <pre data-filename="background.js">
248 var myWin = null;
250 chrome.app.runtime.onLaunched.addListener(function() {
251 chrome.app.window.create('sandboxed.html', {
252 'bounds': {
253 'width': 400,
254 'height': 400
256 }, function(win) {
257 myWin = win;
258 myWin.contentWindow.postMessage('Just wanted to say hey.', '*');
261 </pre>
264 Generally speaking on the web,
265 you want to specify the exact origin
266 from where the message is sent.
267 Chrome Apps have no access
268 to the unique origin of sandboxed content,
269 so you can only whitelist all origins
270 as acceptable origins ('*').
271 On the receiving end,
272 you generally want to check the origin;
273 but since Chrome Apps content is contained,
274 it isn't necessary.
275 To find out more,
276 see <a href="https://developer.mozilla.org/en/DOM/window.postMessage">window.postMessage</a>.
277 </p>
279 <h3 id="listen_message">Listen for message and reply</h3>
282 Here's a sample message receiver
283 that gets added to your sandboxed page:
284 </p>
286 <pre data-filename="sandboxed.html">
287 var messageHandler = function(event) {
288 console.log('Background script says hello.', event.data);
290 // Send a reply
291 event.source.postMessage(
292 {'reply': 'Sandbox received: ' + event.data}, event.origin);
295 window.addEventListener('message', messageHandler);
296 </pre>
299 For more details, check out the
300 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/samples/sandbox">sandbox</a> sample.
301 </p>
303 <p class="backtotop"><a href="#top">Back to top</a></p>