OLD | NEW |
(Empty) | |
| 1 <h1>Embed Content</h1> |
| 2 |
| 3 |
| 4 <p> |
| 5 The <a href="app_architecture.html#security">packaged apps security model</a> di
sallows |
| 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> |
| 11 |
| 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> |
| 19 |
| 20 <p class="note"> |
| 21 <b>API Samples: </b> |
| 22 Want to play with the code? |
| 23 Check out the |
| 24 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/eval-in-
iframe">eval-in-iframe</a> |
| 25 and <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/rege
x-tester">regex-tester</a> samples. |
| 26 </p> |
| 27 |
| 28 <h2 id="external">Referencing external resources</h2> |
| 29 |
| 30 <p> |
| 31 The <a href="app_csp.html">Content Security Policy</a> used by apps disallows |
| 32 the use of many kinds of remote URLs, so you can't directly reference external |
| 33 images, stylesheets, or fonts from an app page. Instead, you can use use |
| 34 cross-origin XMLHttpRequests to fetch these resources, |
| 35 and then serve them via <code>blob:</code> URLs. |
| 36 </p> |
| 37 |
| 38 <h3>Manifest requirement</h3> |
| 39 |
| 40 <p> |
| 41 To be able to do cross-origin XMLHttpRequests, you'll need to add a permission |
| 42 for the remote URL's host: |
| 43 </p> |
| 44 |
| 45 <pre> |
| 46 "permissions": [ |
| 47 "...", |
| 48 "https://supersweetdomainbutnotcspfriendly.com/" |
| 49 ] |
| 50 </pre> |
| 51 |
| 52 <h3>Cross-origin XMLHttpRequest</h3> |
| 53 |
| 54 <p> |
| 55 Fetch the remote URL into the app and serve its contents as a <code>blob:</code> |
| 56 URL: |
| 57 </p> |
| 58 |
| 59 <pre> |
| 60 var xhr = new XMLHttpRequest(); |
| 61 xhr.open('GET', 'https://supersweetdomainbutnotcspfriendly.com/image.png', true)
; |
| 62 xhr.responseType = 'blob'; |
| 63 xhr.onload = function(e) { |
| 64 var img = document.createElement('img'); |
| 65 img.src = window.webkitURL.createObjectURL(this.response); |
| 66 document.body.appendChild(img); |
| 67 }; |
| 68 |
| 69 xhr.send(); |
| 70 </pre> |
| 71 |
| 72 <p>You may want to <a href="offline_apps.html#saving-locally">save</a> |
| 73 these resources locally, so that they are available offline.</p> |
| 74 |
| 75 <h2 id="browsertag">Embed external web pages</h2> |
| 76 |
| 77 <p class="note"> |
| 78 <b>API Sample: </b> |
| 79 Want to play with the code? Check out the |
| 80 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/browser-
tag">browser-tag</a> |
| 81 sample. |
| 82 </p> |
| 83 |
| 84 <p> |
| 85 The <code>browser</code> tag allows you to embed external web content in your |
| 86 app, for example, a web page. It replaces iframes that point to remote URLs, |
| 87 which are disabled inside packaged apps. Unlike iframes, the |
| 88 <code>browser</code> tag runs in a separate process. This means that an exploit |
| 89 inside of it will still be isolated and won't be able to gain elevated |
| 90 privileges. Further, since its storage (cookies, etc.) is isolated from the app, |
| 91 there is no way for the web content to access any of the app's data. |
| 92 </p> |
| 93 |
| 94 <h3>Add browser element</h3> |
| 95 |
| 96 <p> |
| 97 Your <code>browser</code> element must include the URL to the source content |
| 98 and specify its dimensions. |
| 99 </p> |
| 100 |
| 101 <pre><browser src="http://news.google.com/" width="640" height="480"></bro
wser></pre> |
| 102 |
| 103 <h3>Update properties</h3> |
| 104 |
| 105 <p> |
| 106 To dynamically change the <code>src</code>, <code>width</code> and |
| 107 <code>height</code> properties of a <code>browser</code> tag, you can either |
| 108 set those properties directly on the JavaScript object, or use the |
| 109 <code>setAttribute</code> DOM function. |
| 110 </p> |
| 111 |
| 112 <pre> |
| 113 document.querySelector('#mybrowser').src = |
| 114 'http://blog.chromium.org/'; |
| 115 // or |
| 116 document.querySelector('#mybrowser').setAttribute( |
| 117 'src', 'http://blog.chromium.org/'); |
| 118 </pre> |
| 119 |
| 120 <h2 id="sandboxing">Sandbox local content</h2> |
| 121 |
| 122 <p> |
| 123 Sandboxing allows specified pages |
| 124 to be served in a sandboxed, unique origin. |
| 125 These pages are then exempt from their Content Security Policy. |
| 126 Sandboxed pages can use iframes, inline scripting, |
| 127 and <code>eval()</code>. |
| 128 Check out the manifest field description for |
| 129 <a href="manifest.html#sandbox">sandbox</a>. |
| 130 </p> |
| 131 |
| 132 <p> |
| 133 It's a trade-off though: |
| 134 sandboxed pages can't use the chrome.* APIs. |
| 135 If you need to do things like <code>eval()</code>, |
| 136 go this route to be exempt from CSP, |
| 137 but you won't be able to use the cool new stuff. |
| 138 </p> |
| 139 |
| 140 <h3>Use inline scripts in sandbox</h3> |
| 141 |
| 142 <p> |
| 143 Here's a sample sandboxed page |
| 144 which uses an inline script and <code>eval()</code>: |
| 145 </p> |
| 146 |
| 147 <pre> |
| 148 <html> |
| 149 <body> |
| 150 <h1>Woot</h1> |
| 151 <script> |
| 152 document.write('I am an inline script.<br>'); |
| 153 eval('document.write(\'I am an eval-ed inline script.\');'); |
| 154 </script> |
| 155 </body> |
| 156 </html> |
| 157 </pre> |
| 158 |
| 159 <h3>Include sandbox in manifest</h3> |
| 160 |
| 161 <p> |
| 162 You need to include the <code>sandbox</code> field in the manifest |
| 163 and list the app pages to be served in a sandbox: |
| 164 </p> |
| 165 |
| 166 <pre> |
| 167 "sandbox": { |
| 168 "pages": ["sandboxed.html"] |
| 169 } |
| 170 </pre> |
| 171 |
| 172 <h3>Opening a sandboxed page in a window</h3> |
| 173 |
| 174 <p> |
| 175 Just like any other app pages, |
| 176 you can create a window that the sandboxed page opens in. |
| 177 Here's a sample that creates two windows, |
| 178 one for the main app window that isn't sandboxed, |
| 179 and one for the sandboxed page: |
| 180 </p> |
| 181 |
| 182 <pre> |
| 183 chrome.experimental.app.onLaunched.addListener(function() { |
| 184 chrome.app.window.create('window.html', { |
| 185 'width': 400, |
| 186 'height': 400, |
| 187 'left': 0, |
| 188 'top': 0 |
| 189 }); |
| 190 |
| 191 chrome.app.window.create('sandboxed.html', { |
| 192 'width': 400, |
| 193 'height': 400, |
| 194 'left': 400, |
| 195 'top': 0 |
| 196 }); |
| 197 }); |
| 198 </pre> |
| 199 |
| 200 <h3>Embedding a sandboxed page in an app page</h3> |
| 201 |
| 202 <p>Sandboxed pages can also be embedded within another app page |
| 203 using an <code>iframe</code>:</p> |
| 204 |
| 205 <pre> |
| 206 <!DOCTYPE html> |
| 207 <html> |
| 208 <head> |
| 209 </head> |
| 210 <body> |
| 211 <p>I am normal app window.</p> |
| 212 |
| 213 <iframe src="sandboxed.html" width="300" height="200"></iframe> |
| 214 </body> |
| 215 </html> |
| 216 </pre> |
| 217 |
| 218 |
| 219 <h2 id="postMessage">Sending messages to sandboxed pages</h2> |
| 220 |
| 221 <p> |
| 222 There are two parts to sending a message: |
| 223 you need to post a message from the sender page/window, |
| 224 and listen for messages on the receiving page/window. |
| 225 </p> |
| 226 |
| 227 <h3>Post message</h3> |
| 228 |
| 229 <p> |
| 230 You can use <code>postMessage</code> to communicate |
| 231 between your app and sandboxed content. |
| 232 Here's a sample background script |
| 233 that posts a message to the sandboxed page it |
| 234 opens: |
| 235 </p> |
| 236 |
| 237 <pre> |
| 238 var myWin = null; |
| 239 |
| 240 chrome.experimental.app.onLaunched.addListener(function() { |
| 241 chrome.app.window.create('sandboxed.html', { |
| 242 'width': 400, |
| 243 'height': 400 |
| 244 }, function(win) { |
| 245 myWin = win; |
| 246 myWin.postMessage('Just wanted to say hey.', '*'); |
| 247 }); |
| 248 }); |
| 249 </pre> |
| 250 |
| 251 <p> |
| 252 Generally speaking on the web, |
| 253 you want to specify the exact origin |
| 254 from where the message is sent. |
| 255 Packaged apps have no access |
| 256 to the unique origin of sandboxed content, |
| 257 so you can only whitelist all origins |
| 258 as acceptable origins ('*'). |
| 259 On the receiving end, |
| 260 you generally want to check the origin; |
| 261 but since packaged apps content is contained, |
| 262 it isn't necessary. |
| 263 To find out more, |
| 264 see <a href="https://developer.mozilla.org/en/DOM/window.postMessage">window.pos
tMessage</a>. |
| 265 </p> |
| 266 |
| 267 <h3>Listen for message</h3> |
| 268 |
| 269 <p> |
| 270 Here's a sample message receiver |
| 271 that gets added to your sandboxed page: |
| 272 </p> |
| 273 |
| 274 <pre> |
| 275 var messageHandler = function(e) { |
| 276 console.log('Background script says hello.', e.data); |
| 277 }; |
| 278 |
| 279 window.addEventListener('message', messageHandler); |
| 280 </pre> |
| 281 |
| 282 <p class="backtotop"><a href="#top">Back to top</a></p> |
OLD | NEW |