Index: chrome/common/extensions/docs/server2/templates/articles/xhr.html |
diff --git a/chrome/common/extensions/docs/server2/templates/articles/xhr.html b/chrome/common/extensions/docs/server2/templates/articles/xhr.html |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4e25240497e6360304fe476391b8b2dd19a1fc4f |
--- /dev/null |
+++ b/chrome/common/extensions/docs/server2/templates/articles/xhr.html |
@@ -0,0 +1,161 @@ |
+<h1>Cross-Origin XMLHttpRequest</h1> |
+ |
+ |
+<p id="classSummary"> |
+Regular web pages can use the |
+<a href="http://www.w3.org/TR/XMLHttpRequest/">XMLHttpRequest</a> |
+object to send and receive data from remote servers, |
+but they're limited by the |
+<a href="http://en.wikipedia.org/wiki/Same_origin_policy">same origin policy</a>. |
+Extensions aren't so limited. |
+An extension can talk to remote servers outside of its origin, |
+as long as it first requests cross-origin permissions.</p> |
+ |
+<p class="note"> |
+<b>Version note:</b> |
+As of Chrome 13, |
+content scripts can make cross-origin requests |
+to the same servers as the rest of the extension. |
+Before Chrome 13, a content script couldn't directly make requests; |
+instead, it had to |
+send a message to its parent extension |
+asking the extension to make a cross-origin request. |
+</p> |
+ |
+<h2 id="extension-origin">Extension origin</h2> |
+<p>Each running extension exists within its own separate security origin. Without |
+requesting additional privileges, the extension can use |
+XMLHttpRequest to get resources within its installation. For example, if |
+an extension contains a JSON configuration file called <code>config.json</code>, |
+in a <code>config_resources</code> folder, the extension can retrieve the file's contents like |
+this:</p> |
+ |
+<pre> |
+var xhr = new XMLHttpRequest(); |
+xhr.onreadystatechange = handleStateChange; // Implemented elsewhere. |
+xhr.open("GET", chrome.extension.getURL('/config_resources/config.json'), true); |
+xhr.send(); |
+</pre> |
+ |
+<p>If the extension attempts to use a security origin other than itself, |
+say http://www.google.com, |
+the browser disallows it |
+unless the extension has requested the appropriate cross-origin permissions. |
+</p> |
+ |
+<h2 id="requesting-permission">Requesting cross-origin permissions</h2> |
+ |
+<p>By adding hosts or host match patterns (or both) to the |
+<a href="manifest.html#permissions">permissions</a> section of the |
+<a href="manifest.html">manifest</a> file, the extension can request access to |
+remote servers outside of its origin.</p> |
+ |
+<pre>{ |
+ "name": "My extension", |
+ ... |
+ <b>"permissions": [ |
+ "http://www.google.com/" |
+ ]</b>, |
+ ... |
+}</pre> |
+ |
+<p>Cross-origin permission values can be fully qualified host names, |
+like these:</p> |
+ |
+<ul> |
+ <li> "http://www.google.com/" </li> |
+ <li> "http://www.gmail.com/" </li> |
+</ul> |
+ |
+<p>Or they can be match patterns, like these:</p> |
+ |
+<ul> |
+ <li> "http://*.google.com/" </li> |
+ <li> "http://*/" </li> |
+</ul> |
+ |
+<p> |
+A match pattern of "http://*/" allows HTTP access to all reachable domains. |
+Note that here, |
+match patterns are similar to <a href="match_patterns.html">content script |
+match patterns</a>, |
+but any path information following the host is ignored.</p> |
+ |
+<p>Also note that access is granted both by host and by scheme. If an extension |
+wants both secure and non-secure HTTP access to a given host or set |
+of hosts, it must declare the permissions separately:</p> |
+ |
+<pre>"permissions": [ |
+ "http://www.google.com/", |
+ "https://www.google.com/" |
+] |
+</pre> |
+ |
+<h2 id="security-considerations">Security considerations</h2> |
+ |
+<p> |
+When using resources retrieved via XMLHttpRequest, your background page should |
+be careful not to fall victim to <a |
+href="http://en.wikipedia.org/wiki/Cross-site_scripting">cross-site |
+scripting</a>. Specifically, avoid using dangerous APIs such as the below: |
+</p> |
+<pre>background.html |
+=============== |
+var xhr = new XMLHttpRequest(); |
+xhr.open("GET", "http://api.example.com/data.json", true); |
+xhr.onreadystatechange = function() { |
+ if (xhr.readyState == 4) { |
+ // WARNING! Might be evaluating an evil script! |
+ var resp = eval("(" + xhr.responseText + ")"); |
+ ... |
+ } |
+} |
+xhr.send(); |
+ |
+background.html |
+=============== |
+var xhr = new XMLHttpRequest(); |
+xhr.open("GET", "http://api.example.com/data.json", true); |
+xhr.onreadystatechange = function() { |
+ if (xhr.readyState == 4) { |
+ // WARNING! Might be injecting a malicious script! |
+ document.getElementById("resp").innerHTML = xhr.responseText; |
+ ... |
+ } |
+} |
+xhr.send(); |
+</pre> |
+<p> |
+Instead, prefer safer APIs that do not run scripts: |
+</p> |
+<pre>background.html |
+=============== |
+var xhr = new XMLHttpRequest(); |
+xhr.open("GET", "http://api.example.com/data.json", true); |
+xhr.onreadystatechange = function() { |
+ if (xhr.readyState == 4) { |
+ // JSON.parse does not evaluate the attacker's scripts. |
+ var resp = JSON.parse(xhr.responseText); |
+ } |
+} |
+xhr.send(); |
+ |
+background.html |
+=============== |
+var xhr = new XMLHttpRequest(); |
+xhr.open("GET", "http://api.example.com/data.json", true); |
+xhr.onreadystatechange = function() { |
+ if (xhr.readyState == 4) { |
+ // innerText does not let the attacker inject HTML elements. |
+ document.getElementById("resp").innerText = xhr.responseText; |
+ } |
+} |
+xhr.send(); |
+</pre> |
+<p> |
+Additionally, be especially careful of resources retrieved via HTTP. If your |
+extension is used on a hostile network, an network attacker (aka a <a |
+href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack">"man-in-the-middle"</a>) |
+could modify the response and, potentially, attack your extension. Instead, |
+prefer HTTPS whenever possible. |
+</p> |