1 <div id="pageData-name" class="pageData">Cross-Origin XMLHttpRequest</div> 2 3 <!-- BEGIN AUTHORED CONTENT --> 4 <p id="classSummary"> 5 Regular web pages can use the 6 <a href="http://www.w3.org/TR/XMLHttpRequest/">XMLHttpRequest</a> 7 object to send and receive data from remote servers, 8 but they're limited by the 9 <a href="http://en.wikipedia.org/wiki/Same_origin_policy">same origin policy</a>. 10 Extensions aren't so limited. 11 An extension can talk to remote servers outside of its origin, 12 as long as it first requests cross-origin permissions.</p> 13 14 <p class="note"> 15 <b>Note:</b> 16 Content scripts can't directly make cross-origin requests. 17 However, a content script can 18 send a message to its parent extension 19 that asks the extension to make a cross-origin request. 20 For 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 26 requesting additional privileges, the extension can use 27 XMLHttpRequest to get resources within its installation. For example, if 28 an extension contains a JSON configuration file called <code>config.json</code>, 29 in a <code>config_resources</code> folder, the extension can retrieve the file's contents like 30 this:</p> 31 32 <pre> 33 var xhr = new XMLHttpRequest(); 34 xhr.onreadystatechange = handleStateChange; // Implemented elsewhere. 35 xhr.open("GET", chrome.extension.getURL('/config_resources/config.json'), true); 36 xhr.send(); 37 </pre> 38 39 <p>If the extension attempts to use a security origin other than itself, 40 say http://www.google.com, 41 the browser disallows it 42 unless 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 50 remote 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, 62 like 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> 77 A match pattern of "http://*/" allows HTTP access to all reachable domains. 78 Note that here, 79 match patterns are similar to <a href="match_patterns.html">content script 80 match patterns</a>, 81 but 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 84 wants both secure and non-secure HTTP access to a given host or set 85 of 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> 96 When using resources retrieved via XMLHttpRequest, your background page should 97 be careful not to fall victim to <a 98 href="http://en.wikipedia.org/wiki/Cross-site_scripting">cross-site 99 scripting</a>. Specifically, avoid using dangerous APIs such as the below: 100 </p> 101 <pre>background.html 102 =============== 103 var xhr = new XMLHttpRequest(); 104 xhr.open("GET", "http://api.example.com/data.json", true); 105 xhr.onreadystatechange = function() { 106 if (xhr.readyState == 4) { 107 // WARNING! Might be evaluating an evil script! 108 var resp = eval("(" + xhr.responseText + ")"); 109 ... 110 } 111 } 112 xhr.send(); 113 114 background.html 115 =============== 116 var xhr = new XMLHttpRequest(); 117 xhr.open("GET", "http://api.example.com/data.json", true); 118 xhr.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 } 125 xhr.send(); 126 </pre> 127 <p> 128 Instead, prefer safer APIs that do not run scripts: 129 </p> 130 <pre>background.html 131 =============== 132 var xhr = new XMLHttpRequest(); 133 xhr.open("GET", "http://api.example.com/data.json", true); 134 xhr.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 } 140 xhr.send(); 141 142 background.html 143 =============== 144 var xhr = new XMLHttpRequest(); 145 xhr.open("GET", "http://api.example.com/data.json", true); 146 xhr.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 } 152 xhr.send(); 153 </pre> 154 <p> 155 Additionally, be especially careful of resource retrieved via HTTP. If your 156 extension is used on a hostile network, an network attacker (aka a <a 157 href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack">"man-in-the-middle"</a>) 158 could modify the response and, potentially, attack your extension. Instead, 159 prefer HTTPS whenever possible. 160 </p> 161 162 <!-- END AUTHORED CONTENT --> 163