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