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