Index: chrome/common/extensions/docs/server2/templates/articles/offline_apps.html |
diff --git a/chrome/common/extensions/docs/server2/templates/articles/offline_apps.html b/chrome/common/extensions/docs/server2/templates/articles/offline_apps.html |
new file mode 100644 |
index 0000000000000000000000000000000000000000..80b735370fe2b3b728b8ac8bd04f8f1ecf2d2e2f |
--- /dev/null |
+++ b/chrome/common/extensions/docs/server2/templates/articles/offline_apps.html |
@@ -0,0 +1,314 @@ |
+<h1>Offline First</h1> |
+ |
+ |
+<p> |
+Because internet connections can be flakey or non-existent, |
+you need to consider <em>offline first</em>: |
+write your app as if it has no internet connection. |
+Once your app works offline, |
+add whatever network functionality you need |
+for your app to do more when it’s online. |
+Read on for tips on implementing your offline-enabled app. |
+</p> |
+ |
+<h2 id="overview"> Overview </h2> |
+ |
+<p> |
+Packaged apps get the following for free: |
+</p> |
+ |
+<ul> |
+ <li> Your app’s files—all of its JavaScript, |
+ CSS, and fonts, plus other resources it needs |
+ (such as images)—are <b>already downloaded</b>. </li> |
+ <li> Your app can <b>save and optionally sync</b> |
+ small amounts of data using the |
+ <a href="storage.html">Chrome Storage API</a>. </li> |
+ <li> Your app can <b>detect changes in connectivity</b> |
+ by listening for |
+ <a href="https://developer.mozilla.org/en/Online_and_offline_events">online and offline events</a>. </li> |
+</ul> |
+ |
+<p> |
+But those abilities aren't enough to guarantee that your app |
+will work offline. |
+Your offline-enabled app should follow these rules: |
+</p> |
+ |
+<dl> |
+ <dt> Use local data whenever possible. </dt> |
+ <dd> When using resources from the internet, |
+ use <code>XMLHttpRequest</code> to get it, |
+ and then save the data locally. |
+ You can use the Chrome Storage API, |
+ IndexedDB, or |
+ Filesystem API to save data locally. </dd> |
+ |
+ <dt> Separate your app’s UI from its data. </dt> |
+ <dd> |
+ Separating the UI and data not only |
+ improves your app's design and |
+ eases the task of enabling offline usage, |
+ but also lets you provide other views of the user's data. |
+ An MVC framework can help you keep the UI and data separate. |
+ </dd> |
+ |
+ <dt> Assume your app can be closed at any time. </dt> |
+ <dd> Save application state |
+ (both locally and remotely, when possible) |
+ so that users can pick up |
+ wherever they left off. </dd> |
+ |
+ <dt> Test your app thoroughly. </dt> |
+ <dd> Make sure your app works well in both |
+ <a href="#testing">common and tricky scenarios</a>. </dd> |
+</dl> |
+ |
+ |
+<h2 id="possibilities"> Security restrictions </h2> |
+ |
+<p> |
+ Packaged apps are limited |
+ in where they can place their resources: |
+</p> |
+ |
+<ul> |
+ <li> |
+ Because local data |
+ is visible on the user's machine |
+ and can't be securely encrypted, |
+ <b>sensitive data must stay on the server</b>. |
+ For example, don't store passwords or credit card numbers locally. |
+ </li> |
+ <li> All <b>JavaScript</b> that the app executes |
+ must be in the app's package. |
+ It <b>cannot</b> be inline. |
+ <br /> |
+ <span class="comment"> |
+ {PENDING: Should "JavaScript" be "executable code"? |
+ What about NaCl and Dart? Anything else -- shaders, e.g.?} |
+ </span> |
+ </li> |
+ <li> All <b>CSS styles</b>, <b>images</b>, and <b>fonts</b> |
+ can be initially located |
+ either in the app's package |
+ or at a remote URL. |
+ If the resource is remote, |
+ you can't specify it in your HTML. |
+ Instead, get the data using <code>XMLHttpRequest</code> |
+ (see <a href="app_external.html#external">Referencing external resources</a>). |
+ Then either refer to the data with a blob URL |
+ or (better yet) save and then load the data using the |
+ <a href="app_storage.html">Filesystem API</a>. |
+ |
+ <p class="note"> |
+ <b>Note:</b> |
+ Styles can be inline or in separate <code>.css</code> files. |
+ </p> |
+ |
+ </li> |
+</ul> |
+ |
+<p> |
+You can, however, |
+load large media resources such as videos and sounds |
+from external sites. |
+One reason for this exception to the rule |
+is that the <video> and <audio> elements |
+have good fallback behavior when an app |
+has limited or no connectivity. |
+Another reason is that fetching and serving media |
+with <code>XMLHttpRequest</code> and blob URLs |
+currently does not allow |
+streaming or partial buffering. |
+</p> |
+ |
+<p> |
+To provide a sandboxed iframe, |
+you can create an <object> tag. |
+Its contents can be remote, |
+but it has no direct access to the Chrome app APIs |
+(see <a href="app_external.html#objecttag">Embed external web pages</a>). |
+</p> |
+ |
+<p> |
+Some of the restrictions on packaged apps are enforced by the |
+<a href="app_csp.html">Content Security Policy (CSP)</a> |
+which is always the following and cannot be changed for packaged apps: |
+</p> |
+ |
+<pre> |
+default-src 'self'; |
+connect-src *; |
+style-src 'self' blob: data: filesystem: 'unsafe-inline'; |
+img-src 'self' blob: data: filesystem:; |
+frame-src 'self' blob: data: filesystem:; |
+font-src 'self' blob: data: filesystem:; |
+media-src *; |
+</pre> |
+ |
+<h2 id="manifest"> Specifying offline_enabled </h2> |
+ |
+<p> |
+It is assumed that your app behaves well offline. If it doesn't, you should |
+advertise that fact, so that its launch icon is dimmed when the user is offline. |
+To do so, set <code>offline_enabled</code> to <code>false</code> in the |
+<a href="manifest.html">app manifest file</a>: |
+</p> |
+ |
+<pre> |
+{ |
+ "name": "My app", |
+ ... |
+ <b>"offline_enabled": false,</b> |
+ "manifest_version": 2, |
+ ... |
+} |
+</pre> |
+ |
+<p class="comment"> |
+{PENDING: should we link to <a href="https://chrome.google.com/webstore/category/collection/offline_enabled">Offline Apps collection</a>? |
+show a screenshot of how offline apps are highlighted? |
+anything else?} |
+</p> |
+ |
+<h2 id="saving-locally"> Saving data locally </h2> |
+ |
+<p> |
+The following table shows your options for saving data locally |
+(see also <a href="app_storage.html">Manage Data</a>). |
+</p> |
+ |
+<table> |
+<tr> |
+ <th> API </th> <th> Best use </th> <th> Notes </th> |
+</tr> |
+<tr> |
+ <td> Chrome Storage API </td> |
+ <td> Small amounts of string data </td> |
+ <td> Great for settings and state. |
+ Easy to sync remotely (but you don't have to). |
+ Not good for larger amounts of data, |
+ due to quotas. |
+ </td> |
+</tr> |
+<tr> |
+ <td> IndexedDB API </td> |
+ <td> Structured data </td> |
+ <td> Enables fast searches on data. |
+ Use with the |
+ <a href="manifest.html#permissions">unlimitedStorage permission</a>. </td> |
+</tr> |
+<tr> |
+ <td> Filesystem API </td> |
+ <td> Anything else </td> |
+ <td> Provides a sandboxed area where you can store files. |
+ Use with the |
+ <a href="manifest.html#permissions">unlimitedStorage permission</a>. </td> |
+</tr> |
+</table> |
+ |
+<p class="note"> |
+<b>Note:</b> |
+Packaged apps cannot use Web SQL Database or localStorage. |
+The WebSQL specification has been deprecated for awhile now, |
+and localStorage handles data synchronously |
+(which means it can be slow). |
+The Storage API handles data asynchronously. |
+</p> |
+ |
+ |
+<h2 id="saving-remotely"> Saving data remotely </h2> |
+ |
+<p> |
+In general, how you save data remotely is up to you, |
+but some frameworks and APIs can help |
+(see <a href="app_frameworks.html">MVC Architecture</a>). |
+If you use the Chrome Storage API, |
+then all syncable data |
+is automatically synced |
+whenever the app is online |
+and the user is signed in to Chrome. |
+If the user isn't signed in, |
+they'll be prompted to sign in. |
+However, note that the user's synced data |
+is deleted if the user uninstalls your app. |
+<span class="comment"> |
+{QUESTION: true?} |
+</span> |
+</p> |
+ |
+<p> |
+Consider saving users' data for at least |
+30 days after your app is uninstalled, |
+so that users will have a good experience |
+if they reinstall your app. |
+</p> |
+ |
+ |
+<h2 id="mvc"> Separating UI from data </h2> |
+ |
+<p> |
+Using an MVC framework can help you design and implement your app |
+so that the data is completely separate from the app's |
+view on the data. |
+See <a href="app_frameworks.html">MVC Architecture</a> |
+for a list of MVC frameworks. |
+</p> |
+ |
+<p> |
+If your app talks to a custom server, |
+the server should give you data, |
+not chunks of HTML. |
+Think in terms of RESTful APIs. |
+</p> |
+ |
+<p> |
+Once your data is separate from your app, |
+it's much easier to provide alternate views of the data. |
+For example, |
+you might provide a website view of any public data. |
+Not only can a website view |
+be useful when your user is away from Chrome, |
+but it can enable search engines to find the data. |
+</p> |
+ |
+ |
+<h2 id="testing"> Testing </h2> |
+ |
+<p> |
+Make sure your app works well under the following circumstances: |
+</p> |
+ |
+<ul> |
+ <li> |
+ The app is installed, and then immediately goes offline. |
+ In other words, the first use of the app is offline. |
+ </li> |
+ <li> |
+ The app is installed on one computer |
+ and then synced to another. |
+ </li> |
+ <li> |
+ The app is uninstalled and then immediately installed again. |
+ </li> |
+ <li> |
+ The app is running on two computers at the same time, |
+ with the same profile. |
+ The app must behave reasonably |
+ when one computer goes offline, |
+ the user does a bunch of stuff on that computer, |
+ and then the computer comes online again. |
+ </li> |
+ <li> |
+ The app has intermittent connectivity, |
+ switching often between online and offline. |
+ </li> |
+</ul> |
+ |
+<p> |
+Also make sure that the app saves <b>no sensitive user data</b> |
+(such as passwords) on the user's machine. |
+</p> |
+ |
+<p class="backtotop"><a href="#top">Back to top</a></p> |