1<div id="pageData-name" class="pageData">Cross-Origin XMLHttpRequest</div> 2 3<!-- BEGIN AUTHORED CONTENT --> 4<p id="classSummary"> 5Regular web pages can use the 6<a href="http://www.w3.org/TR/XMLHttpRequest/">XMLHttpRequest</a> 7object to send and receive data from remote servers, 8but they're limited by the 9<a href="http://en.wikipedia.org/wiki/Same_origin_policy">same origin policy</a>. 10Extensions aren't so limited. 11An extension can talk to remote servers outside of its origin, 12as long as it first requests cross-origin permissions.</p> 13 14<p class="note"> 15<b>Note:</b> 16Content scripts can't directly make cross-origin requests. 17However, a content script can 18send a message to its parent extension 19that asks the extension to make a cross-origin request. 20For an example of this technique, see the 21<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/howto/contentscript_xhr">contentscript_xhr example</a>. 22</p> 23 24<h2 id="extension-origin">Extension origin</h2> 25<p>Each running extension exists within its own separate security origin. Without 26requesting additional privileges, the extension can use 27XMLHttpRequest to get resources within its installation. For example, if 28an extension contains a JSON configuration file called <code>config.json</code>, 29in a <code>config_resources</code> folder, the extension can retrieve the file's contents like 30this:</p> 31 32<pre> 33var xhr = new XMLHttpRequest(); 34xhr.onreadystatechange = handleStateChange; // Implemented elsewhere. 35xhr.open("GET", chrome.extension.getURL('/config_resources/config.json'), true); 36xhr.send(); 37</pre> 38 39<p>If the extension attempts to use a security origin other than itself, 40say http://www.google.com, 41the browser disallows it 42unless the extension has requested the appropriate cross-origin permissions. 43</p> 44 45<h2 id="requesting-permission">Requesting cross-origin permissions</h2> 46 47<p>By adding hosts or host match patterns (or both) to the 48<a href="manifest.html#permissions">permissions</a> section of the 49<a href="manifest.html">manifest</a> file, the extension can request access to 50remote servers outside of its origin.</p> 51 52<pre>{ 53 "name": "My extension", 54 ... 55 <b>"permissions": [ 56 "http://www.google.com/" 57 ]</b>, 58 ... 59}</pre> 60 61<p>Cross-origin permission values can be fully qualified host names, 62like these:</p> 63 64<ul> 65 <li> "http://www.google.com/" </li> 66 <li> "http://www.gmail.com/" </li> 67</ul> 68 69<p>Or they can be match patterns, like these:</p> 70 71<ul> 72 <li> "http://*.google.com/" </li> 73 <li> "http://*/" </li> 74</ul> 75 76<p> 77A match pattern of "http://*/" allows HTTP access to all reachable domains. 78Note that here, 79match patterns are similar to <a href="match_patterns.html">content script 80match patterns</a>, 81but any path information following the host is ignored.</p> 82 83<p>Also note that access is granted both by host and by scheme. If an extension 84wants both secure and non-secure HTTP access to a given host or set 85of hosts, it must declare the permissions separately:</p> 86 87<pre>"permissions": [ 88 "http://www.google.com/", 89 "https://www.google.com/" 90] 91</pre> 92 93<h2 id="security-considerations">Security considerations</h2> 94 95<p> 96When using resources retrieved via XMLHttpRequest, your background page should 97be careful not to fall victim to <a 98href="http://en.wikipedia.org/wiki/Cross-site_scripting">cross-site 99scripting</a>. Specifically, avoid using dangerous APIs such as the below: 100</p> 101<pre>background.html 102=============== 103var xhr = new XMLHttpRequest(); 104xhr.open("GET", "http://api.example.com/data.json", true); 105xhr.onreadystatechange = function() { 106 if (xhr.readyState == 4) { 107 // WARNING! Might be evaluating an evil script! 108 var resp = eval("(" + xhr.responseText + ")"); 109 ... 110 } 111} 112xhr.send(); 113 114background.html 115=============== 116var xhr = new XMLHttpRequest(); 117xhr.open("GET", "http://api.example.com/data.json", true); 118xhr.onreadystatechange = function() { 119 if (xhr.readyState == 4) { 120 // WARNING! Might be injecting a malicious script! 121 document.getElementById("resp").innerHTML = xhr.responseText; 122 ... 123 } 124} 125xhr.send(); 126</pre> 127<p> 128Instead, prefer safer APIs that do not run scripts: 129</p> 130<pre>background.html 131=============== 132var xhr = new XMLHttpRequest(); 133xhr.open("GET", "http://api.example.com/data.json", true); 134xhr.onreadystatechange = function() { 135 if (xhr.readyState == 4) { 136 // JSON.parse does not evaluate the attacker's scripts. 137 var resp = JSON.parse(xhr.responseText); 138 } 139} 140xhr.send(); 141 142background.html 143=============== 144var xhr = new XMLHttpRequest(); 145xhr.open("GET", "http://api.example.com/data.json", true); 146xhr.onreadystatechange = function() { 147 if (xhr.readyState == 4) { 148 // innerText does not let the attacker inject HTML elements. 149 document.getElementById("resp").innerText = xhr.responseText; 150 } 151} 152xhr.send(); 153</pre> 154<p> 155Additionally, be especially careful of resource retrieved via HTTP. If your 156extension is used on a hostile network, an network attacker (aka a <a 157href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack">"man-in-the-middle"</a>) 158could modify the response and, potentially, attack your extension. Instead, 159prefer HTTPS whenever possible. 160</p> 161 162<!-- END AUTHORED CONTENT --> 163