├── .github └── workflows │ └── generate.yml ├── .gitignore ├── .pr-preview.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── docs ├── index.bs ├── spec │ ├── service_worker │ │ └── index.html │ └── service_worker_1 │ │ └── index.html ├── sw-registration-figure.svg └── v1 │ └── index.bs ├── explainer.md ├── implementation_considerations.md ├── publish ├── service_worker │ ├── FPWD-service-workers-20140501 │ │ ├── assets │ │ │ └── web-spec-framework │ │ │ │ ├── LICENSE │ │ │ │ ├── README.md │ │ │ │ ├── algorithm.html │ │ │ │ ├── base.css │ │ │ │ ├── bower.json │ │ │ │ ├── bower_components │ │ │ │ ├── platform │ │ │ │ │ ├── .bower.json │ │ │ │ │ ├── AUTHORS │ │ │ │ │ ├── CONTRIBUTING.md │ │ │ │ │ ├── LICENSE │ │ │ │ │ ├── PATENTS │ │ │ │ │ ├── README.md │ │ │ │ │ ├── bower.json │ │ │ │ │ ├── build.log │ │ │ │ │ ├── platform.js │ │ │ │ │ └── platform.js.map │ │ │ │ ├── polymer-ajax │ │ │ │ │ ├── .bower.json │ │ │ │ │ ├── AUTHORS │ │ │ │ │ ├── CONTRIBUTING.md │ │ │ │ │ ├── LICENSE │ │ │ │ │ ├── PATENTS │ │ │ │ │ ├── bower.json │ │ │ │ │ ├── docs.json │ │ │ │ │ ├── index.html │ │ │ │ │ ├── polymer-ajax.html │ │ │ │ │ ├── polymer-xhr.html │ │ │ │ │ ├── smoke.html │ │ │ │ │ └── test │ │ │ │ │ │ ├── html │ │ │ │ │ │ └── polymer-ajax.html │ │ │ │ │ │ ├── js │ │ │ │ │ │ └── polymer-ajax.js │ │ │ │ │ │ └── runner.html │ │ │ │ └── polymer │ │ │ │ │ ├── .bower.json │ │ │ │ │ ├── LICENSE │ │ │ │ │ ├── README.md │ │ │ │ │ ├── bower.json │ │ │ │ │ ├── build.log │ │ │ │ │ ├── component.json │ │ │ │ │ ├── composer.json │ │ │ │ │ ├── package.json │ │ │ │ │ ├── polymer-body.html │ │ │ │ │ ├── polymer.html │ │ │ │ │ ├── polymer.js │ │ │ │ │ └── polymer.js.map │ │ │ │ ├── clause.html │ │ │ │ ├── framework.html │ │ │ │ ├── idl.html │ │ │ │ ├── include.js │ │ │ │ ├── promise-0.1.1.min.js │ │ │ │ ├── section.html │ │ │ │ ├── section.js │ │ │ │ ├── toc.html │ │ │ │ └── toc.js │ │ └── index.html │ ├── WD-service-workers-20141113 │ │ └── index.html │ ├── WD-service-workers-20141118 │ │ └── index.html │ ├── WD-service-workers-20150205 │ │ └── index.html │ ├── WD-service-workers-20150625 │ │ └── index.html │ └── WD-service-workers-20160830 │ │ ├── index.bs │ │ └── index.html └── service_worker_1 │ ├── CR-service-workers-20191119 │ └── index.html │ └── WD-service-workers-1-20161011 │ ├── index.bs │ └── index.html ├── w3c.json └── why_not_appcache++.md /.github/workflows/generate.yml: -------------------------------------------------------------------------------- 1 | # Create a file called .github/workflows/auto-publish.yml 2 | name: CI 3 | on: 4 | pull_request: {} 5 | push: 6 | branches: [main] 7 | jobs: 8 | main: 9 | name: Build, Validate and Deploy Locally 10 | runs-on: ubuntu-22.04 11 | steps: 12 | - uses: actions/checkout@v4 13 | - uses: w3c/spec-prod@v2 14 | with: 15 | GH_PAGES_BRANCH: gh-pages 16 | TOOLCHAIN: bikeshed 17 | SOURCE: docs/index.bs 18 | DESTINATION: docs/index.html 19 | VALIDATE_MARKUP: true 20 | BUILD_FAIL_ON: fatal 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .tern-port 3 | docs/index.html 4 | docs/v1/index.html 5 | -------------------------------------------------------------------------------- /.pr-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "docs/index.bs", 3 | "type": "bikeshed", 4 | "params": { 5 | "force": 1 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Web Applications Working Group 2 | 3 | ## Spec and API development 4 | 5 | For the nitty-gritty of the API, the [draft W3C specification](https://w3c.github.io/ServiceWorker/) is authoritative. For implementers and developers who seek a more stable version, [Service Workers 1](https://w3c.github.io/ServiceWorker/v1/) is a right document with which the contributors only focus on fixing bugs and resolving compatibility issues. 6 | 7 | Spec development happens via [issues in this repository](https://github.com/w3c/ServiceWorker/issues). For general discussion, please use the [public-webapps@w3.org mailing list](http://lists.w3.org/Archives/Public/public-webapps/) with a `Subject:` prefix of `[service-workers]`. 8 | 9 | Updates to the spec must reference [resolved issues marked `needs spec`](https://github.com/w3c/ServiceWorker/issues?q=is%3Aclosed+label%3A%22needs+spec%22). 10 | 11 | To make edits to the design, please send pull requests against the Nightly spec on the master branch. We use [bikeshed](https://github.com/tabatkins/bikeshed). So, change and submit `docs/index.bs`. When your pull request is merged, Travis CI will automatically build the spec. 12 | 13 | For normative changes, a corresponding [web-platform-tests](https://github.com/web-platform-tests/wpt) PR is highly appreciated. Typically, both PRs will be merged at the same time. Note that a test change that contradicts the spec should not be merged before the corresponding spec change. If testing is not practical, please explain why and if appropriate [file an issue](https://github.com/web-platform-tests/wpt/issues/new) to follow up later. Add the `type:untestable` or `type:missing-coverage` label as appropriate. 14 | 15 | Contributions to this repository are intended to become part of Recommendation-track documents 16 | governed by the [W3C Patent Policy](https://www.w3.org/policies/patent-policy/) and 17 | [Software and Document License](http://www.w3.org/Consortium/Legal/copyright-software). To contribute, you must 18 | either participate in the relevant W3C Working Group or make a non-member patent licensing 19 | commitment. 20 | 21 | If you are not the sole contributor to a contribution (pull request), please identify all 22 | contributors in the pull request's body or in subsequent comments. 23 | 24 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 25 | 26 | ``` 27 | +@github_username 28 | ``` 29 | 30 | If you added a contributor by mistake, you can remove them in a comment with: 31 | 32 | ``` 33 | -@github_username 34 | ``` 35 | 36 | If you are making a pull request on behalf of someone else but you had no part in designing the 37 | feature, you can remove yourself with the above syntax. 38 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All documents in this Repository are licensed by contributors under the [W3C Software and Document license](http://www.w3.org/Consortium/Legal/copyright-software). 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## What’s going on here? 2 | 3 | Service workers are a new browser feature that provide event-driven scripts that run independently of web pages. Unlike other workers, service workers can be shut down at the end of events, note the lack of retained references from documents, and they have access to domain-wide events such as network fetches. 4 | 5 | Service workers also have scriptable caches. Along with the ability to respond to network requests from certain web pages via script, this provides a way for applications to “go offline”. 6 | 7 | Service workers are meant to replace the ([oft maligned](http://alistapart.com/article/application-cache-is-a-douchebag)) [HTML5 Application Cache](https://html.spec.whatwg.org/multipage/browsers.html#offline). Unlike AppCache, service workers are comprised of scriptable primitives with an extensive use of [Promises](//developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise) that make it possible for application developers to build URL-friendly, always-available applications in a sane and layered way. 8 | 9 | To understand the design and how you might build apps with service workers, see the [explainer document](explainer.md). 10 | 11 | ## Spec and API development 12 | 13 | For the nitty-gritty of the API, the draft W3C specifications are authoritative. [Service Workers Nightly](https://w3c.github.io/ServiceWorker/) is a living document. [Service Workers 1](https://w3c.github.io/ServiceWorker/v1/) is a subset of the nightly version that is advancing toward a W3C Recommendation. For implementers and developers who seek all the latest features, [Service Workers Nightly](https://w3c.github.io/ServiceWorker/) is a right document that is constantly reflecting new requirements. For version 1, contributors plan to focus on fixing bugs and resolving compatibility issues without including new features from the nightly version. 14 | 15 | Spec development happens via [issues in this repository](https://github.com/w3c/ServiceWorker/issues). For general discussion, please use the [public-webapps@w3.org mailing list](http://lists.w3.org/Archives/Public/public-webapps/) with a `Subject:` prefix of `[service-workers]`. 16 | 17 | Updates to the spec must reference [resolved issues marked `needs spec`](https://github.com/w3c/ServiceWorker/issues?q=is%3Aclosed+label%3A%22needs+spec%22). 18 | 19 | To make edits to the design, please send pull requests against the Nightly spec on the master branch. We use [bikeshed](https://github.com/tabatkins/bikeshed). So, change `docs/index.bs` and submit it with the corresponding bikesheded `index.html`. 20 | 21 | ## Examples 22 | 23 | The W3C Web Mobile Group have defined a [series of use-cases where service worker is particularly useful](https://github.com/w3c-webmob/ServiceWorkersDemos). You can help by adding more use cases, draft implementation code, or even working examples once browsers support the required APIs. 24 | 25 | 26 | ## About labels and milestones on issues 27 | This is to explain how we use labels and milestones to triage the issues. Note: This is a draft, suggestions for improvements are welcomed. 28 | 29 | 30 | ### Prioritization 31 | - **enhancement**: is for anything that was assessed as not having any impact on the decisions for the current milestone and can therefore be safely discussed, rejected or prioritized later. 32 | - **milestone**: is used to mark issues we agreed to get done in principle by a given revision. For the sake of efficiency, we tend to only focus on the current milestone and leave everything else without specific milestones. 33 | - **impacts MVP**: is used to mark issues impacting the “Minimal Viable Product”. The MVP is the minimal scope of API that can solve actual use cases. These issues have the highest priority. 34 | 35 | *Risk labels for impacts MVP issues* 36 | 37 | - **medium risk**: to further refine the “impacts MVP” issues. It indicates that the issue is moderately complex and that reaching a conclusion might take some time. These are of higher priority than issues with no risk label but are of lower priority than issues with a “high risk” label. 38 | - **high risk**: to further refine the “impacts MVP” issues. It indicates that the issue is significantly complex and that reaching a conclusion might take a lot of time and effort. These are of higher priority than issues with no risk label or a “medium risk” label. 39 | 40 | 41 | 42 | ### Actions 43 | - **needs spec**: a decision has been made and the spec needs to be updated. 44 | - **spec detail**: has no significant implications for implementers nor web developers. 45 | - **decided**: to record that a decision has been made. 46 | - **invalid**: when something doesn’t constitute a valid issue. 47 | - **wontfix**: a decision has been made not to pursue this issue further. 48 | - **duplicate**: when a similar issue has already been filed. 49 | - **bug**: an oversight that needs to be fixed. 50 | 51 | 52 | ### Areas 53 | - **fetch**: relates to Fetch 54 | - **lifecycle**: relates to lifecycle aspects of service worker 55 | - **cache**: relevant to the Cache APIs 56 | - **question**: not an actual issue. Items that have been filed in order to gain a better understanding of service worker. 57 | -------------------------------------------------------------------------------- /docs/spec/service_worker/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Moved… 6 | 7 | 8 |

Moved to 9 | https://w3c.github.io/ServiceWorker/

10 | -------------------------------------------------------------------------------- /docs/spec/service_worker_1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Moved… 6 | 7 | 8 |

Moved to 9 | https://w3c.github.io/ServiceWorker/v1/

10 | -------------------------------------------------------------------------------- /docs/sw-registration-figure.svg: -------------------------------------------------------------------------------- 1 | RegisterUpdateInstallActivatenavigator.serviceWorker.register()registration.update()Soft Updatefetchscript matchregistrationCreateUnregisterDeleteactivewaitinginstalling^^^Handle Service Worker Client Unloadon errorwhen uninstalling flag is setregistration.unregister()PushManagerSyncManagerGeofenceManagerServiceWorkerRegistrationClear Registrationon error -------------------------------------------------------------------------------- /explainer.md: -------------------------------------------------------------------------------- 1 | # Service workers explained 2 | 3 | ## What’s all this then? 4 | 5 | Service workers are being developed to answer frequent questions and concerns about the web platform, including: 6 | 7 | * An inability to explain (in the [Extensible Web Manifesto](https://extensiblewebmanifesto.org/) sense) HTTP caching and high-level HTTP interactions like the HTML5 AppCache 8 | * Difficulty in building offline-first web applications in a natural way 9 | * The lack of a background execution context which many proposed capabilities could make use of 10 | 11 | We also note that the long lineage of declarative-only solutions ([Google Gears](https://gears.google.com), [Dojo Offline](http://www.sitepen.com/blog/category/dojo-offline/), and [HTML5 AppCache](http://alistapart.com/article/application-cache-is-a-douchebag)) have failed to deliver on their promise. Each successive declarative-only approach failed in many of the same ways, so the service worker effort has taken a different design approach: a largely-imperative system that puts developers firmly in control. 12 | 13 | The service worker is like a [shared worker](https://html.spec.whatwg.org/multipage/workers.html#sharedworker) in that it: 14 | 15 | * Runs in its own global script context (usually in its own thread) 16 | * Isn’t tied to a particular page 17 | * Has no DOM access 18 | 19 | Unlike a shared worker, it: 20 | 21 | * Can run without any page at all 22 | * Can terminate when it isn’t in use, and run again when needed (i.e., it’s event-driven) 23 | * Has a defined upgrade model 24 | * Is HTTPS only (more on that in a bit) 25 | 26 | We can use service workers: 27 | 28 | * To make sites work [faster and/or offline](https://www.youtube.com/watch?v=px-J9Ghvcx4) using network intercepting 29 | * As a basis for other ‘background’ features such as [push messaging](http://updates.html5rocks.com/2015/03/push-notificatons-on-the-open-web) and [background synchronization](https://github.com/slightlyoff/BackgroundSync/blob/master/explainer.md) 30 | 31 | ## Getting started 32 | 33 | First you need to register for a service worker: 34 | 35 | ```js 36 | if ('serviceWorker' in navigator) { 37 | navigator.serviceWorker.register('/my-app/sw.js').then(function(reg) { 38 | console.log('Yey!', reg); 39 | }).catch(function(err) { 40 | console.log('Boo!', err); 41 | }); 42 | } 43 | ``` 44 | 45 | In this example, `/my-app/sw.js` is the location of the service worker script, and it controls pages whose URL begins with `/my-app/`. 46 | 47 | `.register` returns a promise. If you’re new to promises, check out the [HTML5Rocks article](http://www.html5rocks.com/en/tutorials/es6/promises/). 48 | 49 | Some restrictions: 50 | 51 | * The registering page must have been served securely (HTTPS without cert errors) 52 | * The service worker script must be on the same origin as the page, although you can import scripts from other origins using [`importScripts`](https://html.spec.whatwg.org/multipage/workers.html#apis-available-to-workers:dom-workerglobalscope-importscripts) 53 | * …as must the scope 54 | 55 | ### HTTPS only you say? 56 | 57 | Using service workers you can hijack connections, respond differently, & filter responses. Powerful stuff. While you would use these powers for good, a man-in-the-middle might not. To avoid this, you can only register for service workers on pages served over HTTPS, so we know the service worker the browser receives hasn’t been tampered with during its journey through the network. 58 | 59 | GitHub Pages are served over HTTPS, so they’re a great place to host demos. 60 | 61 | ## Initial lifecycle 62 | 63 | Your worker script goes through three stages when you call `.register`: 64 | 65 | 1. Download 66 | 2. Install 67 | 3. Activate 68 | 69 | You can use events to interact with `install` and `activate`: 70 | 71 | ```js 72 | self.addEventListener('install', function(event) { 73 | event.waitUntil( 74 | fetchStuffAndInitDatabases() 75 | ); 76 | }); 77 | 78 | self.addEventListener('activate', function(event) { 79 | // You're good to go! 80 | }); 81 | ``` 82 | 83 | You can pass a promise to `event.waitUntil` to extend the installation process. Once `activate` fires, your service worker can control pages! 84 | 85 | ## So I’m controlling pages now? 86 | 87 | Well, not quite. A document will pick a service worker to be its controller when it navigates, so the document you called `.register` from isn’t being controlled, because there wasn’t a service worker there when it first loaded. 88 | 89 | If you refresh the document, it’ll be under the service worker’s control. You can check `navigator.serviceWorker.controller` to see which service worker is in control, or `null` if there isn’t one. Note: when you’re updating from one service worker to another, things work a little differently. We’ll get into that in the “Updating” section. 90 | 91 | If you shift+reload a document, it’ll always load without a controller, which is handy for testing quick CSS & JS changes. 92 | 93 | Documents tend to live their whole life with a particular service worker, or none at all. However, a service worker can call `self.skipWaiting()` ([spec](https://w3c.github.io/ServiceWorker/#service-worker-global-scope-skipwaiting)) to do an immediate takeover of all pages within scope. 94 | 95 | ## Network intercepting 96 | 97 | ```js 98 | self.addEventListener('fetch', function(event) { 99 | console.log(event.request); 100 | }); 101 | ``` 102 | 103 | You get fetch events for: 104 | 105 | * Navigations within your service worker’s scope 106 | * Any requests triggered by those pages, even if they’re to another origin 107 | 108 | This means you get to hear about requests for the page itself, the CSS, JS, images, XHR, beacons… all of it. The exceptions are: 109 | 110 | * iframes & ``s – these will pick their own controller based on their resource URL 111 | * Service workers – requests to fetch/update a service worker don’t go through the service worker 112 | * Requests triggered within a service worker – you’d get a loop otherwise 113 | 114 | The `request` object gives you information about the request such as its URL, method & headers. But the really fun bit, is you can hijack it and respond differently: 115 | 116 | ```js 117 | self.addEventListener('fetch', function(event) { 118 | event.respondWith(new Response("Hello world!")); 119 | }); 120 | ``` 121 | 122 | [Here’s a live demo](https://jakearchibald.github.io/isserviceworkerready/demos/manual-response/). 123 | 124 | `.respondWith` takes a `Response` object or a promise that resolves to one. We’re creating a manual response above. The `Response` object comes from the [Fetch Spec](https://fetch.spec.whatwg.org/#response-class). Also in the spec is the `fetch()` method, which returns a promise for a response, meaning you can get your response from elsewhere: 125 | 126 | ```js 127 | self.addEventListener('fetch', function(event) { 128 | if (/\.jpg$/.test(event.request.url)) { 129 | event.respondWith( 130 | fetch('//www.google.co.uk/logos/…3-hp.gif', { 131 | mode: 'no-cors' 132 | }) 133 | ); 134 | } 135 | }); 136 | ``` 137 | 138 | In the above, I’m capturing requests that end in `.jpg` and instead responding with a Google doodle. `fetch()` requests are [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) by default, but by setting `no-cors` I can use the response even if it doesn’t have CORS access headers (although I can’t access the content with JavaScript). [Here’s a demo of that](https://jakearchibald.github.io/isserviceworkerready/demos/img-rewrite/). 139 | 140 | Promises let you fall back from one method to another: 141 | 142 | ```js 143 | self.addEventListener('fetch', function(event) { 144 | event.respondWith( 145 | fetch(event.request).catch(function() { 146 | return new Response("Request failed!"); 147 | }) 148 | ); 149 | }); 150 | ``` 151 | 152 | The service worker comes with a cache API, making it easy to store responses for reuse later. More on that shortly, but first… 153 | 154 | ## Updating a service worker 155 | 156 | The lifecycle of a service worker is based on Chrome’s update model: do as much as possible in the background, don’t disrupt the user, complete the update when the current version closes. 157 | 158 | Whenever you navigate to a page within scope of your service worker, the browser checks for updates in the background. If the script is byte-different, it’s considered to be a new version, and installed (note: only the script is checked, not external `importScripts`). However, the old version remains in control over pages until all tabs using it are gone (unless `.replace()` is called during install). Then the old version is garbage collected and the new version takes over. 159 | 160 | This avoids the problem of two versions of a site running at the same time, in different tabs – something that happens by default on the web, and is the [source of really tricky bugs](https://twitter.com/jaffathecake/status/502779501936652289). 161 | 162 | Note: Updates obey the freshness headers of the worker script (such as `max-age`), unless the `max-age` is greater than 24 hours, in which case it is capped to 24 hours. 163 | 164 | 165 | ```js 166 | self.addEventListener('install', function(event) { 167 | // this happens while the old version is still in control 168 | event.waitUntil( 169 | fetchStuffAndInitDatabases() 170 | ); 171 | }); 172 | 173 | self.addEventListener('activate', function(event) { 174 | // the old version is gone now, do what you couldn't 175 | // do while it was still around 176 | event.waitUntil( 177 | schemaMigrationAndCleanup() 178 | ) 179 | }); 180 | ``` 181 | 182 | Here’s [how that looks in practice](https://www.youtube.com/watch?v=VEshtDMHYyA). 183 | 184 | Unfortunately refreshing a single tab isn’t enough to allow an old worker to be collected and a new one take over. Browsers make the next page request before unloading the current page, so there isn’t a moment when current active worker can be released. 185 | 186 | The easiest way at the moment is to close & reopen the tab (cmd+w, then cmd+shift+t on Mac), or shift+reload then normal reload. 187 | 188 | ## The cache 189 | 190 | Service worker comes with a [caching API](https://w3c.github.io/ServiceWorker/#cache-objects), letting you create stores of responses keyed by request. 191 | 192 | ```js 193 | self.addEventListener('install', function(event) { 194 | // pre cache a load of stuff: 195 | event.waitUntil( 196 | caches.open('myapp-static-v1').then(function(cache) { 197 | return cache.addAll([ 198 | '/', 199 | '/styles/all.css', 200 | '/styles/imgs/bg.png', 201 | '/scripts/all.js' 202 | ]); 203 | }) 204 | ) 205 | }); 206 | 207 | self.addEventListener('fetch', function(event) { 208 | event.respondWith( 209 | caches.match(event.request).then(function(cachedResponse) { 210 | return cachedResponse || fetch(event.request); 211 | }) 212 | ); 213 | }); 214 | ``` 215 | 216 | Matching within the cache is similar to the browser cache. Method, URL and `vary` headers are taken into account, but freshness headers are ignored. Things are only removed from caches when you remove them. 217 | 218 | You can add individual items to the cache with `cache.put(request, response)`, including ones you’ve created yourself. You can also control matching, [discounting things](https://w3c.github.io/ServiceWorker/#cache-query-options-dictionary) such as query string, methods, and vary headers. 219 | 220 | ## Other service worker–related specifications 221 | 222 | Since service workers can spin up in time for events, they’ve opened up the possibility for other features that happen occasionally in the background, even when the page isn’t open. Such as: 223 | 224 | * [Push](http://w3c.github.io/push-api/) 225 | * [Background sync](https://github.com/slightlyoff/BackgroundSync) 226 | * [Geofencing](https://github.com/slightlyoff/Geofencing) 227 | 228 | ## Conclusions 229 | 230 | This document only scratches the surface of what service workers enable, and isn’t an exhaustive list of all of the available APIs available to controlled pages or service worker instances. Nor does it cover emergent practices for authoring, composing, and upgrading applications architected to use service workers. It is, hopefully, a guide to understanding the promise of service workers and the rich promise of offline-by-default web applications that are URL friendly and scalable. 231 | 232 | ## Acknowledgments 233 | 234 | Many thanks to [Web Personality of the Year nominee](http://www.ubelly.com/thecritters/) Jake (“B.J.”) Archibald, David Barrett-Kahn, Anne van Kesteren, Michael Nordman, Darin Fisher, Alec Flett, Andrew Betts, Chris Wilson, Aaron Boodman, Dave Herman, Jonas Sicking, Greg Billock, Karol Klepacki, Dan Dascalescu, and Christian Liebel for their comments and contributions to this document and to the discussions that have informed it. 235 | -------------------------------------------------------------------------------- /implementation_considerations.md: -------------------------------------------------------------------------------- 1 | # Implementation considerations for service workers 2 | 3 | Or 4 | 5 | ### _What to expect when you’re expecting to implement_ 6 | 7 | So you’ve got a browser engine, are looking into this whole "Service Workers" thing and have some questions. Take heart, dear reader! Your friendly spec designers/authors are here to answer your (anticipated) questions. Want more answers? [File a bug](issues) and tag it `implementation-concern`. 8 | 9 | This doc looks first at key concepts then outlines the [areas of helpful built-in ambiguity ](https://w3c.github.io/ServiceWorker/) that provide opportunities to go fast. Each opportunity includes a list of strategies that implementations might explore to improve service worker performance. 10 | 11 | ## Key concepts 12 | 13 | ### Event-driven workers 14 | 15 | The biggest thing to understand about service workers is that they are _event driven_. Unlike other forms of [Web Worker](http://www.w3.org/TR/workers/), the lifetime of the script execution context of the worker is not related to documents which have handles to the worker. Instead, service workers begin life when events are sent to them, and they can end between events. 16 | 17 | The most performance-sensitive of these events is the `fetch` event for top-level document navigation. To ensure that the decision regarding which (if any) service worker to boot up to handle a `fetch` event, the spec uses a static tuple of origin + URL pattern to map service workers to navigations. This list will change infrequently and is likely to be something you can cache in memory for fast lookup. 18 | 19 | Once a service worker is a match for a particular navigation, a Service Worker instance is created (if one isn’t already running) using the previously cached scripts. It’s reasonable to assume that all of the scripts required to start the worker will be in the local cache at this point, so there’s little reason to worry about network speed or flakiness here (disk flakiness is another question entirely, see “Racing Allowed” below). 20 | 21 | Next, an event is dispatched to the now-running worker. If the worker’s event handler doesn’t call `e.respondWith()`, no further script is implicated in servicing the fetch and normal resource loading can proceed as per usual. If the worker _does_ take a crack at responding to the event, the worker’s life is typically extended to enable it to do whatever work it needs to do to respond (asynchronously, via the `Promise` provided to `respondWith()`) . Once the worker is done handling the event (or not), the UA _is free to shut the worker down_ and only revive it again for the next event. 22 | 23 | It bears repeating: if no event’s lifecycle is keeping the service worker alive, UAs can shut them down and reclaim whatever resources they might have been using. If this doesn’t warm your cold, cold implementer’s heart then you might truly be dead inside. The opportunities to trade space for speed (and vice versa) are massive. The freedom to start and end service workers at a time of your choosing is the stuff good optimization strategies are made off. 24 | 25 | ### Install 26 | 27 | Installation of service workers happens as a result of a document calling: 28 | 29 | ```html 30 | 31 | 34 | ``` 35 | 36 | The service worker might be homunculus… dozens of imports, loads of code. This is the web and every terrible thing that authors _can_ do _will_ be done. This looks bad, right? 37 | 38 | Turns out that service workers have a defined lifecycle that enables us to think about installation as a separate, asynchronous, potentially long-running phase that _doesn’t affect the rest of `index.html`_’s loading process. 39 | 40 | Installation can be low-priority, and no documents will be controlled by the service worker until it succeeds. That means that it’s possible to depend on lots of script and cache many resources in an service worker without worrying about the “load time” of the service worker itself since all subsequent starts of the service worker will come from local disk cache. 41 | 42 | ### Event Dispatch 43 | 44 | Service workers lean on the DOM Events as the entry point for nearly all work. The contract that developers must learn is that they must call `e.waitUntil()` or `e.respondWith()` to lengthen the life of the overall operation. All of the APIs available to them are asynchronous, and the combination of these factors implies that service workers are meant to be async by default. The tools at hand lead developers down this path, and cooperative multi-tasking (à la Node.js) is the way that libraries must be structured, both for performance and to work naturally with the service worker execution model. Lastly, remember that developers can move work off-thread using sub-workers. They’ll also be killed along with their parent service workers, but long-running or CPU intensive work that might otherwise cause potential for becoming unresponsive can be delegated to contexts which will not block the service worker thread. 45 | 46 | ## Good news, everybody! 47 | 48 | Service workers are designed to enable many optimizations. This section covers some of these opportunities and outlines potential strategies for exploiting them. 49 | 50 | _Caveat Emptor_: This document was drafted in early 2014. Architectures and constraints change. The set of areas to consider outlined here is influenced by a lack perfect foreknowledge. Memory and IO might become free. CPU might become expensive. Genetically engineered super-intelligent catdog hybrids may take over the world. YMMV. 51 | 52 | ### Only matching navigations boot service workers 53 | 54 | Lets say `example.com` has a service worker registered and `acme.com` embeds the image `https://example.com/images/kittens.gif`. Since the service worker matching algorithm is primarily based on _navigations_ and not sub-resource requests, a visit to `acme.com` does _not_ boot the service worker for `example.com` for this fetch. Instead, the `onfetch` event is sent to the `acme.com` service worker (if there is one). 55 | 56 | The need to match navigations may still strike you as a performance burden, but there’s reason for hope. First, you’re already matching a likely-larger list to provide `:visited` metadata to renderers. Next, the globbing format is designed to be simple to speed matches. Lastly, since a UA may skip a service worker entirely, it’s feasible for a UA to only match against some set of registered service workers (say, the most recently installed or used). 57 | 58 | UAs may even decide to try harder (match against a larger list of service workers) when offline to help provide a better offline experience. 59 | 60 | #### Strategies 61 | 62 | * __Keep the match list in memory__ 63 | * __Memory-bound the size of the match list__ 64 | * __Only run matching test against top-level navigations__. Sub-resource requests are always sent to the service worker that controls the page (if any) and so don’t need to be matched. Only top-level navigations every need to be sent through the matching algorithm. 65 | 66 | 67 | ### Events implicitly filter 68 | 69 | Only the event handlers registered at the top-level evaluation of the first evaluation (at install time) of a version of a service worker script are guaranteed to be dispatched against in the future. That is to say, if a service worker script doesn’t register an `onfetch` handler _you can avoid ever sending it `fetch` events_. This is a powerful mechanism for trimming the number of times you need to do potentially expensive work by invoking service workers. 70 | 71 | #### Strategies 72 | 73 | * __Prune the navigation match list based on `onfetch` handlers__ 74 | * __Warn service worker authors that use APIs which would need corresponding handlers which are not registered__. E.g., a call to `navigator.requestSync()` against a service worker that doesn’t include an `onsync` handler isn’t likely to be what the author meant to do. 75 | 76 | ### Startup _matters_ 77 | 78 | The performance of evaluation of the service worker script is a key bottleneck to address in ensuring that perceived latency of service worker–controlled documents remains low. It isn’t possible to send the `fetch` event to the worker until it has been evaluated, potentially including code (via `importScripts()`) from other files. 79 | 80 | #### Strategies 81 | 82 | * __Fetch service workers from disk early__. Links in documents to service worker–controlled space constitute one of perhaps many available signals about the likelihood that the next navigation will be to space controlled by a service worker. As discussed in the matching section, querying to understand if a navigation will match a service worker should be made cheap and, therefore, it’s possible to imagine that optimizing implementations may try to pre-fetch service worker scripts from disk based on speculative matches; e.g. the user typing `microsoft.co` in the address bar is perhaps a strong signal that a frequent visitor of `microsoft.com` will want a registered service worker for that origin to be available quickly. As with all speculative optimizations, the real work here is ensuring good hit rates. 83 | * __Interpret__. JIT-only VMs (like V8) are at a startup-time disadvantage due to the time taken by JIT codegen. Service worker scripts aren’t likely to be computation-intensive (and if they are, your engine can detect as much and flag future runs for JITing). Simpler compilation strategies that get the handlers available faster are a good area to investigate inside the service worker execution context. 84 | * __Store service worker scripts as a single unit__. Storage locality still matters, even in 2014. Commodity MLC flash latency is _atrocious_, and spinning disk isn’t getting (much) faster. Since service worker scripts nearly always require their previous `importScripts()` dependencies (which are cached as a group), it pays to store them in a format that reduces the number of seeks/reads necessary to get the service worker started. Also, remember that install-time is async, so there is time/energy available to optimize the storage layout up-front. 85 | * __Cache parse trees or snapshot__. Service worker scripts (and their dependencies) shouldn’t change in a single version of the application. Combined with a reduced API surface area, it’s possible to apply more exotic strategies for efficiently “rehydrating” the startup execution context of the service worker. The spec makes no guarantees about how frequently a service worker context is killed and re-evaluated in relationship to the number of overall events dispatched, so a UA is free to make non-side-effecting global startup appear to be a continuation of a previous execution. 86 | * __Warn on nondeterministic imports__. Service workers are likely to be invoked when offline. This means that any scripts included via `importScripts()` that aren’t from stable URLs _are likely to break when offline_. UAs can help keep developers on the optimization-friendly path by warning at the console whenever a call to `importScripts()` occurs at a location other than the top-level or is based on a non-static string value. 87 | * __Warn on non-trivial global work__. Since service workers “pay” for any globally executed code every time they start, it’s a good idea for implementations to *_STRONGLY_* discourage doing work outside the defined lifecycle events (`oninstall` and `onactivate`). 88 | * __Learn storage/DB patterns__. Service workers are going to need to lean on IDB for state keeping across invocations and `Cache` objects for dealing with HTTP responses. In both cases it’s possible to observe the set of resources most frequently accessed by a particular version of a service worker and work to ensure that they’re cheaply available by the time the service worker is sent a particular event. In particular, speculatively fetching indexes may pay off in some scenarios. 89 | * __Delay shutdown__. The cheapest service worker to start is the one you haven’t killed. Optimizing implementations may consider providing a “grace period” for the shutdown of service worker threads to reduce startup time of subsequent events. This strategy can be further refined with semantic awareness about event types. E.g., a top-level navigation to a service worker is _likely_ to generate sub-resource fetch events soon after. Shutting down the original service worker execution context quickly may be wasteful. 90 | 91 | ### It’s all async 92 | 93 | Aside from `importScripts()`, no synchronous APIs are available to service workers. This is by design. Remaining responsive from the shared service worker context requires ensuring that decisions are made quickly and long-running work can be deferred to underlying (asynchronous) systems. No API will be added to the service worker execution context that can potentially create cross-context mutex holds (e.g., Local Storage) or otherwise block (e.g., synchronous XHR). This discipline makes it simpler to reason about what it means to be a poorly-written service worker script. 94 | 95 | #### Strategies 96 | 97 | * __Prioritize the service worker thread__. Service worker execution is likely to be a sensitive component of overall application performance. Ensure it isn’t getting unscheduled! 98 | * __Warn on long periods of service worker thread work__. Remaining responsive requires yielding to the service worker thread’s event loop. DevTools can provide value by warning developers of long periods of potentially-blocking work that might reduce responsiveness to incoming events. A reasonable, mobile-friendly starting point might be to warn on any function that takes longer than 20ms to return in the fast path (e.g., `onfetch` or `onmessage`). Recommend to users that they move long-running work to sub-workers, to other turns (via new promises), or that they cache expensive work such that it can be returned via an async API (e.g. IDB). 99 | * __Plan features with async in mind__. As you plan to add new features to the platform that you’d like to have exposed to the service worker context, remember that they’ll need to pass the “async only” test. Using Promises is a good first place to start, and reaching out to the editors of the service worker spec early can’t hurt. 100 | * __Write async tests__. Your implementation is going to need to handle a large degree of variability in timing. Testing (and fuzzing) your scheduling behavior to optimize for overall app performance, particularly in the multiple-tab scenario, is key to keeping an eye on the real-world impact of performance tuning. 101 | * __Get smart about return types__. When it comes to dealing in async responses, the word “return” is usually phrased as `e.respondWith()`. What’s replied with is usually an instance of a `Promise` type, but _not all `Promise`s are created equal_. Consider the case of `e.respondWith(e.default())` and `e.respondWith(caches.match(e.request))`. Both return types result in a delegation to an underlying mechanism _with no further service worker interaction_. Since no additional handlers are added to the vended `Promise` object, the receiving event can know that the service worker is effectively out of the loop for the rest of the operation. This allows savvy implementations to avoid re-entering the service worker and reifying `Response` objects in the service worker execution context. 102 | 103 | ### Best effort 104 | 105 | UAs are free to _not_ start service worker for navigations (or other events), _event if they would match a registered and active service worker_. If you find yourself under memory pressure or for some reason don’t happen to think a service worker is necessary or beneficial (e.g., it has previously been killed for abusing CPU, doesn’t respond to requests in a timeline way, or habitually times out and has to be clobbered), the UA is _free to not start it for a given navigation_. This has the knock-on effect that the service worker won’t be consulted for sub-resource requests for the document either. 106 | 107 | UAs, obviously, should try to do their best to enable service workers to do _their_ best in serving meaningful content to users, and we recommend always trying to send sub-resource requests to service workers for documents that begin life based on the service worker in question. 108 | 109 | 110 | ### Installation is not in the fast path 111 | 112 | The first page loaded from an application that calls `navigator.serviceWorker.register()` cannot, by definition, be served from the service worker itself. This illuminates the async nature of service worker installation. Because service worker installation may take a long time (downloading imported scripts and populating `Cache` objects), the lifecycle events for the service worker system are designed to allow authors to inform the UA of installation success. 113 | 114 | Until installation success a registered service worker _will not be sent any performance-sensitive events_. The async nature of installation provides an opportunity for implementations to do extra work to keep the fast-path responsive. 115 | 116 | #### Strategies 117 | 118 | * __Prioritize service worker resource fetching appropriately__. It may improve performance of the installing document to prioritize resource fetches of the foreground page above those of the installing service worker. 119 | * __Do extra work to optimize service worker loading before activation__. UAs have leeway to avoid activating the service worker for navigations until they’re good and ready to do so. Thinks is your chance to optimize the crud out of them. 120 | 121 | ### Racing allowed 122 | 123 | Anecdotal evidence suggests that commodity OSes and hardware perform VERY badly in disk I/O. Some systems are so degraded that local (valid) caches fetched from disk may perform worse than requests for equivalent resources from the network. Improvements in networks, the spread of malware, and the spread of poorly-written virus scanners exacerbate the underlying trend towards poorly performing disk I/O. 124 | 125 | #### Strategies 126 | 127 | * __Learn to race on top-level navigations__. Adapting to historical (local) I/O performance may help UAs decide if and when to avoid using local resources. Service workers may, at first glance, appear to muddy the waters, but fear not! Nothing about the service worker spec forces an implementer to _always_ send navigations to a matching service worker. In fact, the implementation can attempt to go to the network for a top-level navigation while concurrently attempting to dispatch an `onfetch` to the matching service worker. Assuming the UA chooses to render the document produced by the winner of the race, the model from then on is clear. Thanks to the page-ownership model of the service worker design, the first system to respond will “control” sub-resource requests. This means that if a service worker is used, all subsequent sub-resource requests should be sent to the service worker (not raced). If the network wins the race, all sub-resource requests will be sent to the network (not the service worker). 128 | * __Learn to disable service workers__. In extreme cases, if disk is degraded to the extent that service workers can never start quickly, it may be advantageous to simply disable the service worker subsystem entirely. Thanks to the online-fallback model of service workers, applications should continue to function (to the extent that they can). 129 | 130 | ### Cache objects are HTTP-specific 131 | 132 | Objects in `self.caches` are instances of `Cache`. These HTTP-like-cache objects deal _exclusively_ in HTTP `Response` objects. With the exception of programmatic (not automatic) eviction these `Cache` objects are best thought of as a group of native cache items. Most of the operations available for dealing with them mirror HTTP cache query semantics and will likely be familiar to implementers. You know how to make this stuff fast. 133 | 134 | #### Strategies 135 | 136 | * __Store `Response` objects like HTTP cache entries__. It might be tempting to lean on IDB or other general-purpose storage for handling `Cache` entries. Browser HTTP caches have seen a decade+ of tuning for the specific use-case of returning HTTP data to renderers. It may be advantageous to lean on this engineering where possible. 137 | 138 | ### Interaction with prefetch and prerender is sane 139 | 140 | Speculative pre-parsing of documents and CSS resources (not blocking a parser on ` 13 | 14 | ``` 15 | 16 | Before we can accept a contribution to this project, you'll need to sign the 17 | Contributor License Agreement at https://developers.google.com/open-source/cla/individual. 18 | 19 | ### `jk` 20 | 21 | This one isn't really C++-specific: it allows partitioning a main document 22 | into multiple pieces. `other.html`'s body will be copied in place of the 23 | `` element. 24 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/algorithm.html: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 30 | 31 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/base.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 2em 1em 2em 70px; 3 | margin: 0; 4 | font-family: 'Open Sans', sans-serif; 5 | color: black; 6 | background: white; 7 | background-position: top left; 8 | background-attachment: fixed; 9 | background-repeat: no-repeat; 10 | background-image: url(//www.w3.org/StyleSheets/TR/logo-WD); 11 | line-height: 1.5em; 12 | font-size: 14px; 13 | } 14 | 15 | :link { color: #00C; background: transparent } 16 | :visited { color: #609; background: transparent } 17 | a:active { color: #C00; background: transparent } 18 | 19 | a:link img, 20 | a:visited img { 21 | border: none; 22 | } 23 | 24 | .logo > a { 25 | border-bottom: none; 26 | } 27 | 28 | figure { 29 | width: 600px; 30 | margin: 0 auto; 31 | display: block; 32 | } 33 | 34 | figcaption { 35 | font-size: 0.8em; 36 | } 37 | 38 | h1, h2, h3, h4 { 39 | font-family: 'Open Sans', sans-serif; 40 | color: #005A9C; 41 | padding: 0; 42 | margin: 1.5em 0 0.3em 0; 43 | } 44 | 45 | h1 { 46 | font-size: 3em; 47 | line-height: 1em; 48 | margin: 1em 0; 49 | } 50 | 51 | h2, h3 { 52 | margin: 1.5em 0 0.3em 0; 53 | } 54 | 55 | a { 56 | color: black; 57 | } 58 | 59 | code { 60 | background-color: #eee; 61 | font-family: 'Droid Sans Mono', monospace; 62 | font-size: 0.8em; 63 | } 64 | 65 | body > pre.prettyprint, 66 | body > section pre { 67 | background-color: #eee; 68 | padding: 0 2em 1em 2em; 69 | margin: 0; 70 | border: none; 71 | } 72 | 73 | address { 74 | font-style: normal; 75 | } 76 | 77 | object { 78 | margin: 0 auto; 79 | display: block; 80 | } 81 | 82 | header > ul { 83 | font-family: 'Open Sans', sans-serif; 84 | font-size: 0.8em; 85 | list-style: none; 86 | margin: 0 -1em; 87 | padding: 0.3em 0; 88 | background-color: #eee; 89 | } 90 | 91 | header > ul > li { 92 | display: inline; 93 | margin: 0 0 0 1em; 94 | } 95 | 96 | header > ul > li:nth-of-type(3) { 97 | display: inline; 98 | margin: 0 0 0 5em; 99 | } 100 | 101 | header > ul a { 102 | color: #666; 103 | } 104 | 105 | header > ul a:hover { 106 | color: #000; 107 | } 108 | 109 | code > ins { 110 | background-color: #BBFFDF; 111 | text-decoration: none; 112 | } 113 | 114 | code > del { 115 | background-color: #FF979D; 116 | } 117 | 118 | var { 119 | color: #005A9C; 120 | font-style: normal; 121 | } 122 | 123 | dt { 124 | font-weight: bold; 125 | } 126 | 127 | dt, dd { 128 | margin-top: 0; 129 | margin-bottom: 0; 130 | } 131 | 132 | .warning:before { 133 | content: "WARNING: "; 134 | font-weight: bold; 135 | } 136 | 137 | .warning { 138 | padding: 10px 10px; 139 | width: 100%; 140 | background: #fffaba; 141 | box-sizing: border-box; 142 | } 143 | 144 | dfn { 145 | font-style: normal; 146 | font-weight: bold; 147 | background-color: #f9f9f9; 148 | padding: 0 2px; 149 | outline: 1px solid #eee; 150 | } 151 | 152 | dfn.no-references { 153 | background-color: #ffefef; 154 | } 155 | 156 | dfn:target, a:target { 157 | background-color: #FFFF91; 158 | } 159 | 160 | a { 161 | text-decoration: none; 162 | border-bottom: 1px solid #666; 163 | } 164 | 165 | a[href*=dfn-] { 166 | border-bottom: 1px dotted #ccc; 167 | } 168 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web-spec-framework", 3 | "version": "0.1.0-pre", 4 | "description": "A set of custom HTML elements to make writing well-formatted web specifications easier.", 5 | "main": "framework.html", 6 | "homepage": "https://github.com/slightlyof/web-spec-framework", 7 | "ignore": [ 8 | "**/.*", 9 | "bower_components", 10 | "test", 11 | "tests" 12 | ], 13 | "dependencies": { 14 | "polymer": "~0.2.0", 15 | "polymer-ajax": "Polymer/polymer-ajax#0.2.0" 16 | } 17 | } -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/platform/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform", 3 | "main": "platform.js", 4 | "homepage": "https://github.com/Polymer/platform", 5 | "authors": [ 6 | "The Polymer Authors" 7 | ], 8 | "description": "Integrate platform polyfills: load, build, test", 9 | "keywords": [ 10 | "polymer", 11 | "web", 12 | "components" 13 | ], 14 | "license": "BSD", 15 | "private": true, 16 | "version": "0.2.0", 17 | "_release": "0.2.0", 18 | "_resolution": { 19 | "type": "version", 20 | "tag": "0.2.0", 21 | "commit": "2364ac16efa5904e97c27ad8ae93a02332771343" 22 | }, 23 | "_source": "git://github.com/Polymer/platform.git", 24 | "_target": "0.2.0", 25 | "_originalSource": "Polymer/platform" 26 | } -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/platform/AUTHORS: -------------------------------------------------------------------------------- 1 | # Names should be added to this file with this pattern: 2 | # 3 | # For individuals: 4 | # Name 5 | # 6 | # For organizations: 7 | # Organization 8 | # 9 | Google Inc. <*@google.com> 10 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/platform/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Want to contribute to Polymer? Great! 4 | 5 | We are more than happy to accept external contributions to the project in the form of [feedback](https://groups.google.com/forum/?fromgroups=#!forum/polymer-dev), [bug reports](../../issues), and pull requests. 6 | 7 | ## Contributor License Agreement 8 | 9 | Before we can accept patches, there's a quick web form you need to fill out. 10 | 11 | - If you're contributing as an individual (e.g. you own the intellectual property), fill out [this form](http://code.google.com/legal/individual-cla-v1.0.html). 12 | - If you're contributing under a company, fill out [this form](http://code.google.com/legal/corporate-cla-v1.0.html) instead. 13 | 14 | This CLA asserts that contributions are owned by you and that we can license all work under our [license](LICENSE). 15 | 16 | Other projects require a similar agreement: jQuery, Firefox, Apache, Node, and many more. 17 | 18 | [More about CLAs](https://www.google.com/search?q=Contributor%20License%20Agreement) 19 | 20 | ## Initial setup 21 | 22 | Here's an easy guide that should get you up and running: 23 | 24 | 1. Setup Grunt: `sudo npm install -g grunt-cli` 25 | 1. Fork the project on github and pull down your copy. 26 | > replace the {{ username }} with your username and {{ repository }} with the repository name 27 | 28 | git clone git@github.com:{{ username }}/{{ repository }}.git --recursive 29 | 30 | Note the `--recursive`. This is necessary for submodules to initialize properly. If you don't do a recursive clone, you'll have to init them manually: 31 | 32 | git submodule init 33 | git submodule update 34 | 35 | Download and run the `pull-all.sh` script to install the sibling dependencies. 36 | 37 | git clone git://github.com/Polymer/tools.git && tools/bin/pull-all.sh 38 | 39 | 1. Test your change 40 | > in the repo you've made changes to, run the tests: 41 | 42 | cd $REPO 43 | npm install 44 | grunt test 45 | 46 | 1. Commit your code and make a pull request. 47 | 48 | That's it for the one time setup. Now you're ready to make a change. 49 | 50 | ## Submitting a pull request 51 | 52 | We iterate fast! To avoid potential merge conflicts, it's a good idea to pull from the main project before making a change and submitting a pull request. The easiest way to do this is setup a remote called `upstream` and do a pull before working on a change: 53 | 54 | git remote add upstream git://github.com/Polymer/{{ repository }}.git 55 | 56 | Then before making a change, do a pull from the upstream `master` branch: 57 | 58 | git pull upstream master 59 | 60 | To make life easier, add a "pull upstream" alias in your `.gitconfig`: 61 | 62 | [alias] 63 | pu = !"git fetch origin -v; git fetch upstream -v; git merge upstream/master" 64 | 65 | That will pull in changes from your forked repo, the main (upstream) repo, and merge the two. Then it's just a matter of running `git pu` before a change and pushing to your repo: 66 | 67 | git checkout master 68 | git pu 69 | # make change 70 | git commit -a -m 'Awesome things.' 71 | git push 72 | 73 | Lastly, don't forget to submit the pull request. 74 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/platform/LICENSE: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Polymer Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/platform/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Polymer project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Polymer, where such license applies only to those 11 | patent claims, both currently owned or controlled by Google and acquired 12 | in the future, licensable by Google that are necessarily infringed by 13 | this implementation of Polymer. This grant does not include claims 14 | that would be infringed only as a consequence of further modification of 15 | this implementation. If you or your agent or exclusive licensee 16 | institute or order or agree to the institution of patent litigation 17 | against any entity (including a cross-claim or counterclaim in a 18 | lawsuit) alleging that this implementation of Polymer or any code 19 | incorporated within this implementation of Polymer constitutes 20 | direct or contributory patent infringement, or inducement of patent 21 | infringement, then any patent rights granted to you under this License 22 | for this implementation of Polymer shall terminate as of the date 23 | such litigation is filed. 24 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/platform/README.md: -------------------------------------------------------------------------------- 1 | Platform 2 | ======== 3 | 4 | Aggregated polyfills the Polymer platform. 5 | 6 | [![Analytics](https://ga-beacon.appspot.com/UA-39334307-2/Polymer/platform/README)](https://github.com/igrigorik/ga-beacon) 7 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/platform/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform", 3 | "main": "platform.js", 4 | "homepage": "https://github.com/Polymer/platform", 5 | "authors": [ 6 | "The Polymer Authors" 7 | ], 8 | "description": "Integrate platform polyfills: load, build, test", 9 | "keywords": [ 10 | "polymer", 11 | "web", 12 | "components" 13 | ], 14 | "license": "BSD", 15 | "private": true, 16 | "version": "0.2.0" 17 | } -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/platform/build.log: -------------------------------------------------------------------------------- 1 | BUILD LOG 2 | --------- 3 | Build Time: 2014-02-14T15:57:20 4 | 5 | NODEJS INFORMATION 6 | ================== 7 | nodejs: v0.10.25 8 | chai: 1.9.0 9 | grunt: 0.4.2 10 | grunt-audit: 0.0.2 11 | grunt-concat-sourcemap: 0.4.1 12 | grunt-contrib-concat: 0.3.0 13 | grunt-contrib-uglify: 0.3.2 14 | grunt-contrib-yuidoc: 0.5.0 15 | grunt-karma: 0.6.2 16 | karma: 0.10.9 17 | karma-chrome-launcher: 0.1.2 18 | karma-coffee-preprocessor: 0.1.2 19 | karma-crbot-reporter: 0.0.4 20 | karma-firefox-launcher: 0.1.3 21 | karma-html2js-preprocessor: 0.1.0 22 | karma-ie-launcher: 0.1.1 23 | karma-jasmine: 0.1.5 24 | karma-mocha: 0.1.1 25 | karma-phantomjs-launcher: 0.1.2 26 | karma-requirejs: 0.2.1 27 | karma-safari-launcher: 0.1.1 28 | karma-script-launcher: 0.1.0 29 | mocha: 1.17.1 30 | requirejs: 2.1.10 31 | 32 | REPO REVISIONS 33 | ============== 34 | CustomElements: 18efac1ed0fa054536a9efae2ddea678ddb986b1 35 | HTMLImports: 69486ed9670afe6da872ed673e8a8d0448db16a8 36 | NodeBind: eb5ee7941f712cbee755da24ab7553e2d90fb99d 37 | PointerEvents: 1d551ce7af420577f150f5c922fc54b97f04c84d 38 | PointerGestures: 0cded24896294ebecdfdad47583468f714a0a34e 39 | ShadowDOM: 308a7c2e67032f746b5e52f4e27320ffe3a57ecd 40 | TemplateBinding: 279934127f6777bdfb9f752e98eb0da172fbca1b 41 | WeakMap: a0947a9a0f58f5733f464755c3b86de624b00a5d 42 | observe-js: 3ba9aeec73f7864d519fb13c6f38cb10923cdfd9 43 | platform: 6460c3d51b30b50d311eb1d7b055f29affa26f74 44 | polymer-expressions: 470cced7cf167bd164f0b924ceb088dd7a8240b9 45 | 46 | BUILD HASHES 47 | ============ 48 | build/platform.js: d0831d90d53d03c34a5382fdace5432599c97850 -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer-ajax/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polymer-ajax", 3 | "private": true, 4 | "dependencies": { 5 | "polymer": "Polymer/polymer#0.2.0" 6 | }, 7 | "version": "0.2.0", 8 | "homepage": "https://github.com/Polymer/polymer-ajax", 9 | "_release": "0.2.0", 10 | "_resolution": { 11 | "type": "version", 12 | "tag": "0.2.0", 13 | "commit": "ca01054c981e2480bb47c375ffb2d98d7d86807b" 14 | }, 15 | "_source": "git://github.com/Polymer/polymer-ajax.git", 16 | "_target": "0.2.0", 17 | "_originalSource": "Polymer/polymer-ajax" 18 | } -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer-ajax/AUTHORS: -------------------------------------------------------------------------------- 1 | # Names should be added to this file with this pattern: 2 | # 3 | # For individuals: 4 | # Name 5 | # 6 | # For organizations: 7 | # Organization 8 | # 9 | Google Inc. <*@google.com> 10 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer-ajax/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | See https://github.com/Polymer/polymer/blob/master/CONTRIBUTING.md 2 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer-ajax/LICENSE: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Polymer Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer-ajax/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Polymer project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Polymer, where such license applies only to those 11 | patent claims, both currently owned or controlled by Google and acquired 12 | in the future, licensable by Google that are necessarily infringed by 13 | this implementation of Polymer. This grant does not include claims 14 | that would be infringed only as a consequence of further modification of 15 | this implementation. If you or your agent or exclusive licensee 16 | institute or order or agree to the institution of patent litigation 17 | against any entity (including a cross-claim or counterclaim in a 18 | lawsuit) alleging that this implementation of Polymer or any code 19 | incorporated within this implementation of Polymer constitutes 20 | direct or contributory patent infringement, or inducement of patent 21 | infringement, then any patent rights granted to you under this License 22 | for this implementation of Polymer shall terminate as of the date 23 | such litigation is filed. 24 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer-ajax/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polymer-ajax", 3 | "private": true, 4 | "dependencies": { 5 | "polymer": "Polymer/polymer#0.2.0" 6 | }, 7 | "version": "0.2.0" 8 | } -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer-ajax/docs.json: -------------------------------------------------------------------------------- 1 | { 2 | "project": { 3 | "name": "Docs", 4 | "description": "Docs" 5 | }, 6 | "files": { 7 | "..\\..\\polymer-ajax\\polymer-ajax.html": { 8 | "name": "..\\..\\polymer-ajax\\polymer-ajax.html", 9 | "modules": { 10 | "Polymer Elements": 1 11 | }, 12 | "classes": { 13 | "polymer-ajax": 1 14 | }, 15 | "fors": {}, 16 | "namespaces": {} 17 | }, 18 | "..\\..\\polymer-ajax\\polymer-xhr.html": { 19 | "name": "..\\..\\polymer-ajax\\polymer-xhr.html", 20 | "modules": {}, 21 | "classes": { 22 | "polymer-xhr": 1 23 | }, 24 | "fors": {}, 25 | "namespaces": {} 26 | } 27 | }, 28 | "modules": { 29 | "Polymer Elements": { 30 | "name": "Polymer Elements", 31 | "submodules": {}, 32 | "classes": { 33 | "polymer-ajax": 1, 34 | "polymer-xhr": 1 35 | }, 36 | "fors": {}, 37 | "namespaces": {}, 38 | "tag": "module", 39 | "file": "..\\..\\polymer-ajax\\polymer-xhr.html", 40 | "line": 10 41 | } 42 | }, 43 | "classes": { 44 | "polymer-ajax": { 45 | "name": "polymer-ajax", 46 | "shortname": "polymer-ajax", 47 | "classitems": [], 48 | "plugins": [], 49 | "extensions": [], 50 | "plugin_for": [], 51 | "extension_for": [], 52 | "module": "Polymer Elements", 53 | "namespace": "", 54 | "file": "..\\..\\polymer-ajax\\polymer-ajax.html", 55 | "line": 10, 56 | "description": "polymer-ajax can be used to perform XMLHttpRequests.\n\nExample:\n\n \n " 57 | }, 58 | "polymer-xhr": { 59 | "name": "polymer-xhr", 60 | "shortname": "polymer-xhr", 61 | "classitems": [], 62 | "plugins": [], 63 | "extensions": [], 64 | "plugin_for": [], 65 | "extension_for": [], 66 | "module": "Polymer Elements", 67 | "namespace": "", 68 | "file": "..\\..\\polymer-ajax\\polymer-xhr.html", 69 | "line": 10, 70 | "description": "polymer-xhr can be used to perform XMLHttpRequests.\n\nExample:\n\n \n ...\n this.$.xhr.request({url: url, params: params, callback: callback});" 71 | } 72 | }, 73 | "classitems": [ 74 | { 75 | "file": "..\\..\\polymer-ajax\\polymer-ajax.html", 76 | "line": 23, 77 | "description": "Fired when a response is received.", 78 | "itemtype": "event", 79 | "name": "polymer-response", 80 | "class": "polymer-ajax", 81 | "module": "Polymer Elements" 82 | }, 83 | { 84 | "file": "..\\..\\polymer-ajax\\polymer-ajax.html", 85 | "line": 28, 86 | "description": "Fired when an error is received.", 87 | "itemtype": "event", 88 | "name": "polymer-error", 89 | "class": "polymer-ajax", 90 | "module": "Polymer Elements" 91 | }, 92 | { 93 | "file": "..\\..\\polymer-ajax\\polymer-ajax.html", 94 | "line": 33, 95 | "description": "Fired whenever a response or an error is received.", 96 | "itemtype": "event", 97 | "name": "polymer-complete", 98 | "class": "polymer-ajax", 99 | "module": "Polymer Elements" 100 | }, 101 | { 102 | "file": "..\\..\\polymer-ajax\\polymer-ajax.html", 103 | "line": 45, 104 | "description": "The URL target of the request.", 105 | "itemtype": "attribute", 106 | "name": "url", 107 | "type": "string", 108 | "default": "''", 109 | "class": "polymer-ajax", 110 | "module": "Polymer Elements" 111 | }, 112 | { 113 | "file": "..\\..\\polymer-ajax\\polymer-ajax.html", 114 | "line": 53, 115 | "description": "Specifies what data to store in the 'response' property, and\nto deliver as 'event.response' in 'response' events.\n\nOne of:\n\n `text`: uses XHR.responseText\n \n `xml`: uses XHR.responseXML\n \n `json`: uses XHR.responseText parsed as JSON", 116 | "itemtype": "attribute", 117 | "name": "handleAs", 118 | "type": "string", 119 | "default": "'text'", 120 | "class": "polymer-ajax", 121 | "module": "Polymer Elements" 122 | }, 123 | { 124 | "file": "..\\..\\polymer-ajax\\polymer-ajax.html", 125 | "line": 70, 126 | "description": "If true, automatically performs an Ajax request when either url or params has changed.", 127 | "itemtype": "attribute", 128 | "name": "auto", 129 | "type": "boolean", 130 | "default": "false", 131 | "class": "polymer-ajax", 132 | "module": "Polymer Elements" 133 | }, 134 | { 135 | "file": "..\\..\\polymer-ajax\\polymer-ajax.html", 136 | "line": 78, 137 | "description": "Parameters to send to the specified URL, as JSON.", 138 | "itemtype": "attribute", 139 | "name": "params", 140 | "type": "string (JSON)", 141 | "default": "''", 142 | "class": "polymer-ajax", 143 | "module": "Polymer Elements" 144 | }, 145 | { 146 | "file": "..\\..\\polymer-ajax\\polymer-ajax.html", 147 | "line": 86, 148 | "description": "Returns the response object.", 149 | "itemtype": "attribute", 150 | "name": "response", 151 | "type": "Object", 152 | "default": "null", 153 | "class": "polymer-ajax", 154 | "module": "Polymer Elements" 155 | }, 156 | { 157 | "file": "..\\..\\polymer-ajax\\polymer-ajax.html", 158 | "line": 94, 159 | "description": "The HTTP method to use such as 'GET', 'POST', 'PUT', 'DELETE'.\nDefault is 'GET'.", 160 | "itemtype": "attribute", 161 | "name": "method", 162 | "type": "string", 163 | "default": "''", 164 | "class": "polymer-ajax", 165 | "module": "Polymer Elements" 166 | }, 167 | { 168 | "file": "..\\..\\polymer-ajax\\polymer-ajax.html", 169 | "line": 172, 170 | "description": "Performs an Ajax request to the url specified.", 171 | "itemtype": "method", 172 | "name": "go", 173 | "class": "polymer-ajax", 174 | "module": "Polymer Elements" 175 | }, 176 | { 177 | "file": "..\\..\\polymer-ajax\\polymer-xhr.html", 178 | "line": 59, 179 | "description": "Sends a HTTP request to the server and returns the XHR object.", 180 | "itemtype": "method", 181 | "name": "request", 182 | "params": [ 183 | { 184 | "name": "inOptions", 185 | "description": "", 186 | "type": "Object", 187 | "props": [ 188 | { 189 | "name": "url", 190 | "description": "The url to which the request is sent.", 191 | "type": "String" 192 | }, 193 | { 194 | "name": "method", 195 | "description": "The HTTP method to use, default is GET.", 196 | "type": "String" 197 | }, 198 | { 199 | "name": "sync", 200 | "description": "By default, all requests are sent asynchronously.\n To send synchronous requests, set to true.", 201 | "type": "Boolean" 202 | }, 203 | { 204 | "name": "params", 205 | "description": "Data to be sent to the server.", 206 | "type": "Object" 207 | }, 208 | { 209 | "name": "body", 210 | "description": "The content for the request body for POST method.", 211 | "type": "Object" 212 | }, 213 | { 214 | "name": "headers", 215 | "description": "HTTP request headers.", 216 | "type": "Object" 217 | }, 218 | { 219 | "name": "responseType", 220 | "description": "The response type. Default is 'text'.", 221 | "type": "String" 222 | }, 223 | { 224 | "name": "callback", 225 | "description": "Called when request is completed.", 226 | "type": "Object" 227 | } 228 | ] 229 | } 230 | ], 231 | "return": { 232 | "description": "XHR object.", 233 | "type": "Object" 234 | }, 235 | "class": "polymer-xhr", 236 | "module": "Polymer Elements" 237 | } 238 | ], 239 | "warnings": [ 240 | { 241 | "message": "replacing incorrect tag: returns with return", 242 | "line": " ..\\..\\polymer-ajax\\polymer-xhr.html:59" 243 | } 244 | ] 245 | } -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer-ajax/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | polymer api 5 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | [remote] 44 | 45 |
46 | 47 | 63 | 64 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer-ajax/polymer-ajax.html: -------------------------------------------------------------------------------- 1 | 6 | 41 | 42 | 43 | 44 | 45 | 241 | 242 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer-ajax/polymer-xhr.html: -------------------------------------------------------------------------------- 1 | 6 | 22 | 23 | 24 | 25 | 32 | 96 | 97 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer-ajax/smoke.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | polymer-ajax 5 | 6 | 7 | 8 | 9 | 12 | 13 | 16 | 17 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer-ajax/test/html/polymer-ajax.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | polymer-ajax 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 18 | 19 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer-ajax/test/js/polymer-ajax.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Polymer Authors. All rights reserved. 3 | * Use of this source code is governed by a BSD-style 4 | * license that can be found in the LICENSE file. 5 | */ 6 | 7 | htmlSuite('polymer-ajax', function() { 8 | htmlTest('html/polymer-ajax.html'); 9 | }); -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer-ajax/test/runner.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | polymer-ajax Test Runner (Mocha) 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polymer", 3 | "description": "Polymer is a new type of library for the web, built on top of Web Components, and designed to leverage the evolving web platform on modern browsers.", 4 | "homepage": "http://www.polymer-project.org/", 5 | "keywords": [ 6 | "util", 7 | "client", 8 | "browser", 9 | "web components", 10 | "web-components" 11 | ], 12 | "author": "Polymer Authors ", 13 | "version": "0.2.0", 14 | "main": [ 15 | "polymer.js" 16 | ], 17 | "dependencies": { 18 | "platform": "Polymer/platform#0.2.0" 19 | }, 20 | "_release": "0.2.0", 21 | "_resolution": { 22 | "type": "version", 23 | "tag": "0.2.0", 24 | "commit": "e97f8ed465cfffbb2179519f40ec6c1e3955f115" 25 | }, 26 | "_source": "git://github.com/components/polymer.git", 27 | "_target": "~0.2.0", 28 | "_originalSource": "polymer" 29 | } -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer/LICENSE: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014 The Polymer Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer/README.md: -------------------------------------------------------------------------------- 1 | Polymer is a new type of library for the web, built on top of Web Components, and designed to leverage the evolving web platform on modern browsers. 2 | 3 | For Docs, License, Tests, and pre-packed downloads, see: 4 | http://www.polymer-project.org/ 5 | 6 | Many thanks to our contributors: 7 | https://github.com/Polymer/platform/contributors 8 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polymer", 3 | "description": "Polymer is a new type of library for the web, built on top of Web Components, and designed to leverage the evolving web platform on modern browsers.", 4 | "homepage": "http://www.polymer-project.org/", 5 | "keywords": [ 6 | "util", 7 | "client", 8 | "browser", 9 | "web components", 10 | "web-components" 11 | ], 12 | "author": "Polymer Authors ", 13 | "version": "0.2.0", 14 | "main": [ 15 | "polymer.js" 16 | ], 17 | "dependencies": { 18 | "platform": "Polymer/platform#0.2.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer/build.log: -------------------------------------------------------------------------------- 1 | BUILD LOG 2 | --------- 3 | Build Time: 2014-02-14T16:12:52 4 | 5 | NODEJS INFORMATION 6 | ================== 7 | nodejs: v0.10.25 8 | chai: 1.9.0 9 | grunt: 0.4.2 10 | grunt-audit: 0.0.2 11 | grunt-concat-sourcemap: 0.3.2 12 | grunt-contrib-uglify: 0.3.2 13 | grunt-contrib-yuidoc: 0.5.0 14 | grunt-karma: 0.6.2 15 | karma: 0.10.8 16 | karma-chrome-launcher: 0.0.2 (git://github.com/morethanreal/karma-chrome-launcher#aaaef751f4c39b4671447f4b62a3462101f8a3c4) 17 | karma-coffee-preprocessor: 0.1.1 18 | karma-crbot-reporter: 0.0.4 19 | karma-firefox-launcher: 0.1.2 20 | karma-html2js-preprocessor: 0.1.0 21 | karma-ie-launcher: 0.1.1 22 | karma-jasmine: 0.1.4 23 | karma-mocha: 0.1.1 24 | karma-phantomjs-launcher: 0.1.1 25 | karma-requirejs: 0.2.0 26 | karma-safari-launcher: 0.1.1 27 | karma-script-launcher: 0.1.0 28 | mocha: 1.17.1 29 | requirejs: 2.1.9 30 | 31 | REPO REVISIONS 32 | ============== 33 | polymer-dev: cc80e6d0d84c268cf0df1d1b981e8e7ab8abf8be 34 | 35 | BUILD HASHES 36 | ============ 37 | build/polymer.js: a4a98d5d38e01fee39486936ab2c71f506403ffc -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer/component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "platform", 3 | "repo": "components/platform", 4 | "description": "Leverage the future of the web platform today.", 5 | "homepage": "http://www.polymer-project.org/", 6 | "keywords": [ 7 | "util", 8 | "client", 9 | "browser" 10 | ], 11 | "author": "Polymer Authors ", 12 | "version": "0.2.0", 13 | "main": "polymer.js", 14 | "scripts": [ 15 | "polymer.js" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "components/platform", 3 | "description": "Leverage the future of the web platform today.", 4 | "keywords": ["util", "client", "browser"], 5 | "type": "component", 6 | "homepage": "http://www.polymer-project.org/", 7 | "support": { 8 | "issues": "https://github.com/Polymer/platform/issues", 9 | "source": "https://github.com/Polymer/platform" 10 | }, 11 | "authors": [ 12 | { 13 | "name": "Polymer Authors", 14 | "email": "polymer-dev@googlegroups.com" 15 | } 16 | ], 17 | "extra": { 18 | "component": { 19 | "name": "polymer", 20 | "scripts": [ 21 | "polymer.min.js" 22 | ], 23 | "files": [ 24 | "src/**", 25 | "platform/**", 26 | "polymer.min.js", 27 | "polymer.min.js.map", 28 | "polymer.native.min.js", 29 | "polymer.native.min.js.map" 30 | ], 31 | "shim": { 32 | "exports": "Platform" 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "components-polymer", 3 | "description": "Leverage the future of the web platform today.", 4 | "homepage": "http://www.polymer-project.org/", 5 | "keywords": [ 6 | "util", 7 | "client", 8 | "browser" 9 | ], 10 | "author": "Polymer Authors ", 11 | "repository": { 12 | "type": "git", 13 | "url": "git://github.com/Polymer/platform.git" 14 | }, 15 | "main": "polymer.html", 16 | "version": "0.2.0", 17 | "devDependencies": { 18 | "mocha": "*", 19 | "chai": "*", 20 | "grunt": "*", 21 | "grunt-contrib-concat": "*", 22 | "grunt-contrib-uglify": "*", 23 | "grunt-contrib-yuidoc": "~0.4.0", 24 | "grunt-karma-0.9.1": "~0.4.3", 25 | "karma-mocha": "*", 26 | "karma-script-launcher": "*", 27 | "karma-crbot-reporter": "*" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer/polymer-body.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 32 | 33 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer/polymer.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/bower_components/polymer/polymer.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Polymer Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | // @version: 0.2.0 29 | Polymer={},"function"==typeof window.Polymer&&(Polymer={}),function(a){function b(a,b){return a&&b&&Object.getOwnPropertyNames(b).forEach(function(c){var d=Object.getOwnPropertyDescriptor(b,c);d&&(Object.defineProperty(a,c,d),"function"==typeof d.value&&(d.value.nom=c))}),a}a.extend=b}(Polymer),function(a){function b(a,b,d){return a?a.stop():a=new c(this),a.go(b,d),a}var c=function(a){this.context=a,this.boundComplete=this.complete.bind(this)};c.prototype={go:function(a,b){this.callback=a;var c;b?(c=setTimeout(this.boundComplete,b),this.handle=function(){clearTimeout(c)}):(c=requestAnimationFrame(this.boundComplete),this.handle=function(){cancelAnimationFrame(c)})},stop:function(){this.handle&&(this.handle(),this.handle=null)},complete:function(){this.handle&&(this.stop(),this.callback.call(this.context))}},a.job=b}(Polymer),function(){var a={};HTMLElement.register=function(b,c){a[b]=c},HTMLElement.getPrototypeForTag=function(b){var c=b?a[b]:HTMLElement.prototype;return c||Object.getPrototypeOf(document.createElement(b))};var b=Event.prototype.stopPropagation;Event.prototype.stopPropagation=function(){this.cancelBubble=!0,b.apply(this,arguments)}}(Polymer),function(a){function b(a){var c=b.caller,g=c.nom,h=c._super;if(h||(g||(g=c.nom=e.call(this,c)),g||console.warn("called super() on a method not installed declaratively (has no .nom property)"),h=d(c,g,f(this))),h){var i=h[g];return i._super||d(i,g,h),i.apply(this,a||[])}}function c(a,b,c){for(;a;){if(a[b]!==c&&a[b])return a;a=f(a)}}function d(a,b,d){return a._super=c(d,b,a),a._super&&(a._super[b].nom=b),a._super}function e(a){for(var b=this.__proto__;b&&b!==HTMLElement.prototype;){for(var c,d=Object.getOwnPropertyNames(b),e=0,f=d.length;f>e&&(c=d[e]);e++){var g=Object.getOwnPropertyDescriptor(b,c);if("function"==typeof g.value&&g.value===a)return c}b=b.__proto__}}function f(a){return a.__proto__}a.super=b}(Polymer),function(a){function b(a,b){var d=typeof b;return b instanceof Date&&(d="date"),c[d](a,b)}var c={string:function(a){return a},date:function(a){return new Date(Date.parse(a)||Date.now())},"boolean":function(a){return""===a?!0:"false"===a?!1:!!a},number:function(a){var b=parseFloat(a);return 0===b&&(b=parseInt(a)),isNaN(b)?a:b},object:function(a,b){if(null===b)return a;try{return JSON.parse(a.replace(/'/g,'"'))}catch(c){return a}},"function":function(a,b){return b}};a.deserializeValue=b}(Polymer),function(a){var b=a.extend,c={};c.declaration={},c.instance={},c.publish=function(a,c){for(var d in a)b(c,a[d])},a.api=c}(Polymer),function(a){var b={async:function(a,b,c){Platform.flush(),b=b&&b.length?b:[b];var d=function(){(this[a]||a).apply(this,b)}.bind(this),e=c?setTimeout(d,c):requestAnimationFrame(d);return c?e:1/e},cancelAsync:function(a){1>a?cancelAnimationFrame(Math.round(1/a)):clearTimeout(a)},fire:function(a,b,c,d,e){var f=c||this,b=b||{},g=new CustomEvent(a,{bubbles:void 0!==d?d:!0,cancelable:void 0!==e?e:!0,detail:b});return f.dispatchEvent(g),g},asyncFire:function(){this.async("fire",arguments)},classFollows:function(a,b,c){b&&b.classList.remove(c),a&&a.classList.add(c)}},c=function(){},d={};b.asyncMethod=b.async,a.api.instance.utils=b,a.nop=c,a.nob=d}(Polymer),function(a){var b=window.logFlags||{},c="on-",d={EVENT_PREFIX:c,addHostListeners:function(){var a=this.eventDelegates;b.events&&Object.keys(a).length>0&&console.log("[%s] addHostListeners:",this.localName,a);var d,e,f=this;for(var g in a)e=c+g,(d=PolymerExpressions.prepareEventBinding(Path.get(a[g]),e,{resolveEventHandler:function(a,b){var c=b.getValueFrom(f);return c?c.bind(f):void 0}}))(this,this,!1)},dispatchMethod:function(a,c,d){if(a){b.events&&console.group("[%s] dispatch [%s]",a.localName,c);var e="function"==typeof c?c:a[c];e&&e[d?"apply":"call"](a,d),b.events&&console.groupEnd(),Platform.flush()}}};a.api.instance.events=d}(Polymer),function(a){var b={copyInstanceAttributes:function(){var a=this._instanceAttributes;for(var b in a)this.hasAttribute(b)||this.setAttribute(b,a[b])},takeAttributes:function(){if(this._publishLC)for(var a,b=0,c=this.attributes,d=c.length;(a=c[b])&&d>b;b++)this.attributeToProperty(a.name,a.value)},attributeToProperty:function(b,c){var b=this.propertyForAttribute(b);if(b){if(c&&c.search(a.bindPattern)>=0)return;var d=this[b],c=this.deserializeValue(c,d);c!==d&&(this[b]=c)}},propertyForAttribute:function(a){var b=this._publishLC&&this._publishLC[a];return b},deserializeValue:function(b,c){return a.deserializeValue(b,c)},serializeValue:function(a,b){return"boolean"===b?a?"":void 0:"object"!==b&&"function"!==b&&void 0!==a?a:void 0},reflectPropertyToAttribute:function(a){var b=typeof this[a],c=this.serializeValue(this[a],b);void 0!==c?this.setAttribute(a,c):"boolean"===b&&this.removeAttribute(a)}};a.api.instance.attributes=b}(Polymer),function(a){function b(a,b,d){c.bind&&console.log(e,inB.localName||"object",inPath,a.localName,b);var f=d.discardChanges();return(null===f||void 0===f)&&d.setValue(a[b]),Observer.defineComputedProperty(a,b,d)}var c=window.logFlags||{},d={observeProperties:function(){var a=this._observeNames,b=this._publishNames;if(a&&a.length||b&&b.length){for(var c,d=this._propertyObserver=new CompoundObserver,e=0,f=a.length;f>e&&(c=a[e]);e++){d.addPath(this,c);var g=Object.getOwnPropertyDescriptor(this.__proto__,c);g&&g.value&&this.observeArrayValue(c,g.value,null)}for(var c,e=0,f=b.length;f>e&&(c=b[e]);e++)this.observe&&void 0!==this.observe[c]||d.addPath(this,c);d.open(this.notifyPropertyChanges,this)}},notifyPropertyChanges:function(a,b,c){var d,e,f={};for(var g in b)d=c[2*g+1],void 0!==this.publish[d]&&this.reflectPropertyToAttribute(d),e=this.observe[d],e&&(this.observeArrayValue(d,a[g],b[g]),f[e]||(f[e]=!0,this.invokeMethod(e,[b[g],a[g],arguments])))},observeArrayValue:function(a,b,d){var e=this.observe[a];if(e&&(Array.isArray(d)&&(c.observe&&console.log("[%s] observeArrayValue: unregister observer [%s]",this.localName,a),this.unregisterObserver(a+"__array")),Array.isArray(b))){c.observe&&console.log("[%s] observeArrayValue: register observer [%s]",this.localName,a,b);var f=new ArrayObserver(b);f.open(function(a,b){this.invokeMethod(e,[b])},this),this.registerObserver(a+"__array",f)}},bindProperty:function(a,c){return b(this,a,c)},unbindAllProperties:function(){this._propertyObserver&&this._propertyObserver.close(),this.unregisterObservers()},unbindProperty:function(a){return this.unregisterObserver(a)},invokeMethod:function(a,b){var c=this[a]||a;"function"==typeof c&&c.apply(this,b)},registerObserver:function(a,b){var c=this._observers||(this._observers={});c[a]=b},unregisterObserver:function(a){var b=this._observers;return b&&b[a]?(b[a].close(),b[a]=null,!0):void 0},unregisterObservers:function(){if(this._observers){for(var a,b,c=Object.keys(this._observers),d=0,e=c.length;e>d&&(a=c[d]);d++)b=this._observers[a],b.close();this._observers={}}}},e="[%s]: bindProperties: [%s] to [%s].[%s]";a.api.instance.properties=d}(Polymer),function(a){function b(a){for(;a.parentNode;){if(a.lightDomController)return a;a=a.parentNode}return a.host}function c(a){e(a,d)}function d(a){a.unbindAll()}function e(a,b){if(a){b(a);for(var c=a.firstChild;c;c=c.nextSibling)e(c,b)}}var f=window.logFlags||0,g=(a.api.instance.events,new PolymerExpressions);g.resolveEventHandler=function(a,c,d){var e=b(d);if(e){var f=c.getValueFrom(e);if(f)return f.bind(e)}};var h={syntax:g,instanceTemplate:function(a){return a.createInstance(this,this.syntax)},bind:function(a,b){this._elementPrepared||this.prepareElement();var c=this.propertyForAttribute(a);if(c){this.unbind(a);var d=this.bindProperty(c,b);return d.path=b.path_,this.reflectPropertyToAttribute(c),this.bindings[a]=d}return this.mixinSuper(arguments)},asyncUnbindAll:function(){this._unbound||(f.unbind&&console.log("[%s] asyncUnbindAll",this.localName),this._unbindAllJob=this.job(this._unbindAllJob,this.unbindAll,0))},unbindAll:function(){if(!this._unbound){this.unbindAllProperties(),this.super();for(var a=this.shadowRoot;a;)c(a),a=a.olderShadowRoot;this._unbound=!0}},cancelUnbindAll:function(a){return this._unbound?void(f.unbind&&console.warn("[%s] already unbound, cannot cancel unbindAll",this.localName)):(f.unbind&&console.log("[%s] cancelUnbindAll",this.localName),this._unbindAllJob&&(this._unbindAllJob=this._unbindAllJob.stop()),void(a||e(this.shadowRoot,function(a){a.cancelUnbindAll&&a.cancelUnbindAll()})))}},i=/\{\{([^{}]*)}}/;a.bindPattern=i,a.api.instance.mdv=h}(Polymer),function(a){function b(a){return a.hasOwnProperty("PolymerBase")}function c(){}var d=0,e={PolymerBase:!0,job:Polymer.job,"super":Polymer.super,created:function(){},ready:function(){},createdCallback:function(){this.created(),(this.ownerDocument.defaultView||this.alwaysPrepare||d>0)&&this.prepareElement()},prepareElement:function(){this._elementPrepared=!0,this.shadowRoots={},this.observeProperties(),this.copyInstanceAttributes(),this.takeAttributes(),this.addHostListeners(),d++,this.parseDeclarations(this.__proto__),d--,this.removeAttribute("unresolved"),this.ready()},attachedCallback:function(){this._elementPrepared||this.prepareElement(),this.cancelUnbindAll(!0),this.attached&&this.attached(),this.enteredView&&this.enteredView()},detachedCallback:function(){this.preventDispose||this.asyncUnbindAll(),this.detached&&this.detached(),this.leftView&&this.leftView()},enteredViewCallback:function(){this.attachedCallback()},leftViewCallback:function(){this.detachedCallback()},enteredDocumentCallback:function(){this.attachedCallback()},leftDocumentCallback:function(){this.detachedCallback()},parseDeclarations:function(a){a&&a.element&&(this.parseDeclarations(a.__proto__),a.parseDeclaration.call(this,a.element))},parseDeclaration:function(a){var b=this.fetchTemplate(a);if(b){var c=this.shadowFromTemplate(b);this.shadowRoots[a.name]=c}},fetchTemplate:function(a){return a.querySelector("template")},shadowFromTemplate:function(a){if(a){var b=this.createShadowRoot();b.resetStyleInheritance=this.resetStyleInheritance;var c=this.instanceTemplate(a);return b.appendChild(c),this.shadowRootReady(b,a),b}},lightFromTemplate:function(a){if(a){this.lightDomController=!0;var b=this.instanceTemplate(a);return this.appendChild(b),this.shadowRootReady(this,a),b}},shadowRootReady:function(a){this.marshalNodeReferences(a),PointerGestures.register(a)},marshalNodeReferences:function(a){var b=this.$=this.$||{};if(a)for(var c,d=a.querySelectorAll("[id]"),e=0,f=d.length;f>e&&(c=d[e]);e++)b[c.id]=c},attributeChangedCallback:function(a){"class"!==a&&"style"!==a&&this.attributeToProperty(a,this.getAttribute(a)),this.attributeChanged&&this.attributeChanged.apply(this,arguments)},onMutation:function(a,b){var c=new MutationObserver(function(a){b.call(this,c,a),c.disconnect()}.bind(this));c.observe(a,{childList:!0,subtree:!0})}};c.prototype=e,e.constructor=c,a.Base=c,a.isBase=b,a.api.instance.base=e}(Polymer),function(a){function b(a){return a.__proto__}var c=(window.logFlags||{},"element"),d="controller",e={STYLE_SCOPE_ATTRIBUTE:c,installControllerStyles:function(){var a=this.findStyleController();if(a&&!this.scopeHasElementStyle(a,d)){for(var c=b(this),e="";c&&c.element;)e+=c.element.cssTextForScope(d),c=b(c);if(e){var f=this.element.cssTextToScopeStyle(e,d);Polymer.applyStyleToScope(f,a)}}},findStyleController:function(){if(window.ShadowDOMPolyfill)return wrap(document.head);for(var a=this;a.parentNode;)a=a.parentNode;return a===document?document.head:a},scopeHasElementStyle:function(a,b){var d=c+"="+this.localName+"-"+b;return a.querySelector("style["+d+"]")}};a.api.instance.styles=e}(Polymer),function(a){function b(a,b){if(f[a])throw"Already registered (Polymer) prototype for element "+a;e(a,b),d(a)}function c(a,b){h[a]=b}function d(a){h[a]&&(h[a].registerWhenReady(),delete h[a])}function e(a,b){return i[a]=b||{}}function f(a){return i[a]}var g=a.extend,h=(a.api,{}),i={};a.getRegisteredPrototype=f,a.waitingForPrototype=c,window.Polymer=b,g(Polymer,a);var j=Platform.deliverDeclarations();if(j)for(var k,l=0,m=j.length;m>l&&(k=j[l]);l++)b.apply(null,k)}(Polymer),function(a){var b={resolveElementPaths:function(a){Platform.urlResolver.resolveDom(a)},addResolvePathApi:function(){var a=this.getAttribute("assetpath")||"",b=new URL(a,this.ownerDocument.baseURI);this.prototype.resolvePath=function(a,c){var d=new URL(a,c||b);return d.href}}};a.api.declaration.path=b}(Polymer),function(a){function b(a,b){var c=new URL(a.getAttribute("href"),b).href;return"@import '"+c+"';"}function c(a,b){if(a){var c=d(a.textContent),e=a.getAttribute(h);e&&c.setAttribute(h,e),b.appendChild(c)}}function d(a,b){b=b||document,b=b.createElement?b:b.ownerDocument;var c=b.createElement("style");return c.textContent=a,c}function e(a){return a&&a.__resource||""}function f(a,b){return p?p.call(a,b):void 0}var g=(window.logFlags||{},a.api.instance.styles),h=g.STYLE_SCOPE_ATTRIBUTE,i="style",j="@import",k="link[rel=stylesheet]",l="global",m="polymer-scope",n={loadStyles:function(a){var b=this.templateContent();b&&this.convertSheetsToStyles(b);var c=this.findLoadableStyles(b);c.length?window.ShadowDOMPolyfill||this.hasAttribute("cache-csstext")?Platform.loader.xhrStyles(c,a):Platform.loader.cacheStyles(c,a):a&&a()},convertSheetsToStyles:function(a){for(var c,e,f=a.querySelectorAll(k),g=0,h=f.length;h>g&&(c=f[g]);g++){e=d(b(c,this.ownerDocument.baseURI),this.ownerDocument);var i=c.getAttribute(m);i&&e.setAttribute(m,i),c.parentNode.replaceChild(e,c)}},findLoadableStyles:function(a){var b=[];if(a)for(var c,d=a.querySelectorAll(i),e=0,f=d.length;f>e&&(c=d[e]);e++)c.textContent.match(j)&&b.push(c);return b},installSheets:function(){this.cacheSheets(),this.cacheStyles(),this.installLocalSheets(),this.installGlobalStyles()},cacheSheets:function(){this.sheets=this.findNodes(k),this.sheets.forEach(function(a){a.parentNode&&a.parentNode.removeChild(a)})},cacheStyles:function(){this.styles=this.findNodes(i+"["+m+"]"),this.styles.forEach(function(a){a.parentNode&&a.parentNode.removeChild(a)})},installLocalSheets:function(){var a=this.sheets.filter(function(a){return!a.hasAttribute(m)}),b=this.templateContent();if(b){var c="";if(a.forEach(function(a){c+=e(a)+"\n"}),c){var f=d(c,this.ownerDocument);b.insertBefore(f,b.firstChild)}}},findNodes:function(a,b){var c=this.querySelectorAll(a).array(),d=this.templateContent();if(d){var e=d.querySelectorAll(a).array();c=c.concat(e)}return b?c.filter(b):c},templateContent:function(){var a=this.querySelector("template");return a&&templateContent(a)},installGlobalStyles:function(){var a=this.styleForScope(l);c(a,document.head)},cssTextForScope:function(a){var b="",c="["+m+"="+a+"]",d=function(a){return f(a,c)},g=this.sheets.filter(d);g.forEach(function(a){b+=e(a)+"\n\n"});var h=this.styles.filter(d);return h.forEach(function(a){b+=a.textContent+"\n\n"}),b},styleForScope:function(a){var b=this.cssTextForScope(a);return this.cssTextToScopeStyle(b,a)},cssTextToScopeStyle:function(a,b){if(a){var c=d(a);return c.setAttribute(h,this.getAttribute("name")+"-"+b),c}}},o=HTMLElement.prototype,p=o.matches||o.matchesSelector||o.webkitMatchesSelector||o.mozMatchesSelector;a.api.declaration.styles=n,a.applyStyleToScope=c}(Polymer),function(a){var b=(window.logFlags||{},a.api.instance.events),c=b.EVENT_PREFIX,d={parseHostEvents:function(){var a=this.prototype.eventDelegates;this.addAttributeDelegates(a)},addAttributeDelegates:function(a){for(var b,c=0;b=this.attributes[c];c++)this.hasEventPrefix(b.name)&&(a[this.removeEventPrefix(b.name)]=b.value.replace("{{","").replace("}}","").trim())},hasEventPrefix:function(a){return a&&"o"===a[0]&&"n"===a[1]&&"-"===a[2]},removeEventPrefix:function(a){return a.slice(e)}},e=c.length;a.api.declaration.events=d}(Polymer),function(a){var b={inferObservers:function(a){var b,c=a.observe;for(var d in a)"Changed"===d.slice(-7)&&(c||(c=a.observe={}),b=d.slice(0,-7),c[b]=c[b]||d)},explodeObservers:function(a){var b=a.observe;if(b){var c={};for(var d in b)for(var e,f=d.split(" "),g=0;e=f[g];g++)c[e]=b[d];a.observe=c}},optimizePropertyMaps:function(a){if(a.observe){var b=a._observeNames=[];for(var c in a.observe)for(var d,e=c.split(" "),f=0;d=e[f];f++)b.push(d)}if(a.publish){var b=a._publishNames=[];for(var c in a.publish)b.push(c)}},publishProperties:function(a,b){var c=a.publish;c&&(this.requireProperties(c,a,b),a._publishLC=this.lowerCaseMap(c))},requireProperties:function(a,b,c){for(var d in a)void 0===b[d]&&void 0===c[d]&&(b[d]=a[d])},lowerCaseMap:function(a){var b={};for(var c in a)b[c.toLowerCase()]=c;return b}};a.api.declaration.properties=b}(Polymer),function(a){var b="attributes",c=/\s|,/,d={inheritAttributesObjects:function(a){this.inheritObject(a,"publishLC"),this.inheritObject(a,"_instanceAttributes")},publishAttributes:function(a,d){var e=this.getAttribute(b);if(e)for(var f,g=a.publish||(a.publish={}),h=e.split(c),i=0,j=h.length;j>i;i++)f=h[i].trim(),f&&void 0===g[f]&&void 0===d[f]&&(g[f]=null)},accumulateInstanceAttributes:function(){for(var a,b=this.prototype._instanceAttributes,c=this.attributes,d=0,e=c.length;e>d&&(a=c[d]);d++)this.isInstanceAttribute(a.name)&&(b[a.name]=a.value)},isInstanceAttribute:function(a){return!this.blackList[a]&&"on-"!==a.slice(0,3)},blackList:{name:1,"extends":1,constructor:1,noscript:1,assetpath:1,"cache-csstext":1}};d.blackList[b]=1,a.api.declaration.attributes=d}(Polymer),function(a){function b(a){if(!Object.__proto__){var b=Object.getPrototypeOf(a);a.__proto__=b,d(b)&&(b.__proto__=Object.getPrototypeOf(b))}}var c=a.api,d=a.isBase,e=a.extend,f={register:function(a,b){this.buildPrototype(a,b),this.registerPrototype(a,b),this.publishConstructor()},buildPrototype:function(b,c){var d=a.getRegisteredPrototype(b),e=this.generateBasePrototype(c);this.desugarBeforeChaining(d,e),this.prototype=this.chainPrototypes(d,e),this.desugarAfterChaining(b,c)},desugarBeforeChaining:function(a,b){a.element=this,this.publishAttributes(a,b),this.publishProperties(a,b),this.inferObservers(a),this.explodeObservers(a)},chainPrototypes:function(a,c){this.inheritMetaData(a,c);var d=this.chainObject(a,c);return b(d),d},inheritMetaData:function(a,b){this.inheritObject("observe",a,b),this.inheritObject("publish",a,b),this.inheritObject("_publishLC",a,b),this.inheritObject("_instanceAttributes",a,b),this.inheritObject("eventDelegates",a,b)},desugarAfterChaining:function(a,b){this.optimizePropertyMaps(this.prototype),this.installSheets(),this.resolveElementPaths(this),this.accumulateInstanceAttributes(),this.parseHostEvents(),this.addResolvePathApi(),window.ShadowDOMPolyfill&&Platform.ShadowCSS.shimStyling(this.templateContent(),a,b),this.prototype.registerCallback&&this.prototype.registerCallback(this)},publishConstructor:function(){var a=this.getAttribute("constructor");a&&(window[a]=this.ctor)},generateBasePrototype:function(a){var b=this.findBasePrototype(a);if(!b){var b=HTMLElement.getPrototypeForTag(a);b=this.ensureBaseApi(b),g[a]=b}return b},findBasePrototype:function(a){return g[a]},ensureBaseApi:function(a){if(a.PolymerBase)return a;var b=Object.create(a);return c.publish(c.instance,b),this.mixinMethod(b,a,c.instance.mdv,"bind"),b},mixinMethod:function(a,b,c,d){var e=function(a){return b[d].apply(this,a)};a[d]=function(){return this.mixinSuper=e,c[d].apply(this,arguments)}},inheritObject:function(a,b,c){var d=b[a]||{};b[a]=this.chainObject(d,c[a])},registerPrototype:function(a,b){var c={prototype:this.prototype},d=this.findTypeExtension(b);d&&(c.extends=d),HTMLElement.register(a,this.prototype),this.ctor=document.registerElement(a,c),this.prototype.constructor=this.ctor},findTypeExtension:function(a){if(a&&a.indexOf("-")<0)return a;var b=this.findBasePrototype(a);return b.element?this.findTypeExtension(b.element.extends):void 0}},g={};f.chainObject=Object.__proto__?function(a,b){return a&&b&&a!==b&&(a.__proto__=b),a}:function(a,b){if(a&&b&&a!==b){var c=Object.create(b);a=e(c,a)}return a},c.declaration.prototype=f}(Polymer),function(a){function b(a){return document.contains(a)?g:f}function c(){return f.length?f[0]:g[0]}function d(a){e.waitToFlush=!0,HTMLImports.whenImportsReady(function(){e.addReadyCallback(a),e.waitToFlush=!1,e.check()})}var e={wait:function(a){return-1===this.indexOf(a)&&-1===h.indexOf(a)&&this.add(a),0!==this.indexOf(a)},add:function(a){b(a).push(a)},indexOf:function(a){var c=b(a).indexOf(a);return c>=0&&document.contains(a)&&(c+=HTMLImports.useNative||HTMLImports.ready?f.length:1e9),c},register:function(a){var b=this.remove(a);b&&(h.push(b),this.check())},remove:function(a){var c=this.indexOf(a);if(0===c)return b(a).shift()},check:function(){var a=this.nextElement();return a&&a.registerWhenReady(),this.canFlush()?(this.flush(),!0):void 0},nextElement:function(){return c()},canFlush:function(){return!this.waitToFlush&&this.isEmpty()},isEmpty:function(){return!f.length&&!g.length},flush:function(){CustomElements.ready=!1;for(var a;h.length;)a=h.shift(),a._register();CustomElements.upgradeDocumentTree(document),CustomElements.ready=!0,this.flushReadyCallbacks()},flushReadyCallbacks:function(){if(i)for(var a;i.length;)(a=i.shift())()},addReadyCallback:function(a){a&&i.push(a)},waitToFlush:!0},f=[],g=[],h=[],i=[];a.queue=e,a.whenPolymerReady=d}(Polymer),function(a){function b(a,b){if(a){for(var c,e=a.querySelectorAll("link[rel=import]"),f=0,g=e.length;g>f&&(c=e[f]);f++)c.href=c.href;document.head.appendChild(a),d(b)}else b&&b()}function c(a,c){if(a&&a.length){for(var d,e,f=document.createDocumentFragment(),g=0,h=a.length;h>g&&(d=a[g]);g++)e=document.createElement("link"),e.rel="import",e.href=d,f.appendChild(e);b(f,c)}else c&&c()}var d=a.whenPolymerReady;a.import=c,a.importElements=b}(Polymer),function(a){function b(a){return Boolean(HTMLElement.getPrototypeForTag(a))}function c(a){return a&&a.indexOf("-")>=0}var d=a.extend,e=a.api,f=a.queue,g=a.whenPolymerReady,h=a.getRegisteredPrototype,i=a.waitingForPrototype,j=d(Object.create(HTMLElement.prototype),{createdCallback:function(){this.getAttribute("name")&&this.init()},init:function(){this.name=this.getAttribute("name"),this.extends=this.getAttribute("extends"),this.loadResources(),this.registerWhenReady()},registerWhenReady:function(){this.registered||this.waitingForPrototype(this.name)||this.waitingForQueue()||this.waitingForResources()||f.register(this)},_register:function(){c(this.extends)&&!b(this.extends)&&console.warn("%s is attempting to extend %s, an unregistered element or one that was not registered with Polymer.",this.name,this.extends),this.register(this.name,this.extends),this.registered=!0},waitingForPrototype:function(a){return h(a)?void 0:(i(a,this),this.handleNoScript(a),!0)},handleNoScript:function(a){if(this.hasAttribute("noscript")&&!this.noscript)if(this.noscript=!0,window.CustomElements&&!CustomElements.useNative)Polymer(a);else{var b=document.createElement("script");b.textContent="Polymer('"+a+"');",this.appendChild(b)}},waitingForResources:function(){return this._needsResources},waitingForQueue:function(){return f.wait(this)},loadResources:function(){this._needsResources=!0,this.loadStyles(function(){this._needsResources=!1,this.registerWhenReady()}.bind(this))}});e.publish(e.declaration,j),a.getRegisteredPrototype=h,g(function(){document.body.removeAttribute("unresolved"),document.dispatchEvent(new CustomEvent("polymer-ready",{bubbles:!0}))}),document.registerElement("polymer-element",{prototype:j})}(Polymer); 30 | //# sourceMappingURL=polymer.js.map -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/clause.html: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 36 | 37 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/framework.html: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/idl.html: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 38 | 39 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/include.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2014 Google Inc. All rights reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | /* The element replaces itself with the contents at 17 | * 'href'. It doesn't use a shadow root so that the other document 18 | * acts exactly as part of the current document. */ 19 | (function() { 20 | "use strict"; 21 | 22 | var includeProto = Object.create(HTMLElement.prototype, { 23 | attachedCallback: { 24 | value: function() { 25 | this.link = document.createElement('link'); 26 | this.link.setAttribute('rel', 'import'); 27 | this.link.setAttribute('href', this.getAttribute('href')); 28 | this.link.onload = this.loaded.bind(this); 29 | this.link.onerror = function(e) { 30 | console.error(e); 31 | } 32 | document.head.appendChild(this.link); 33 | }, 34 | }, 35 | loaded: { 36 | value: function() { 37 | var imported = this.link.import; 38 | this.link.parentNode.removeChild(this.link); 39 | var parent = this.parentNode; 40 | for (var elem = imported.body.firstChild; 41 | elem; 42 | elem = elem.nextSibling) { 43 | parent.insertBefore(elem.cloneNode(true), this); 44 | } 45 | parent.removeChild(this); 46 | }, 47 | }, 48 | 49 | }); 50 | document.registerElement('spec-include', { prototype: includeProto }); 51 | })(); 52 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/promise-0.1.1.min.js: -------------------------------------------------------------------------------- 1 | !function(){var a,b,c,d;!function(){var e={},f={};a=function(a,b,c){e[a]={deps:b,callback:c}},d=c=b=function(a){function c(b){if("."!==b.charAt(0))return b;for(var c=b.split("/"),d=a.split("/").slice(0,-1),e=0,f=c.length;f>e;e++){var g=c[e];if(".."===g)d.pop();else{if("."===g)continue;d.push(g)}}return d.join("/")}if(d._eak_seen=e,f[a])return f[a];if(f[a]={},!e[a])throw new Error("Could not find module "+a);for(var g,h=e[a],i=h.deps,j=h.callback,k=[],l=0,m=i.length;m>l;l++)"exports"===i[l]?k.push(g={}):k.push(b(c(i[l])));var n=j.apply(this,k);return f[a]=g||n}}(),a("promise/all",["./utils","exports"],function(a,b){"use strict";function c(a){var b=this;if(!d(a))throw new TypeError("You must pass an array to all.");return new b(function(b,c){function d(a){return function(b){f(a,b)}}function f(a,c){h[a]=c,0===--i&&b(h)}var g,h=[],i=a.length;0===i&&b([]);for(var j=0;j 15 | 16 | 20 | 21 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/section.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2014 Google Inc. All rights reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | (function() { 17 | "use strict"; 18 | 19 | Polymer('spec-section', { 20 | // String section number, like "17.2.3". 1-based. 21 | sec_num: "?", 22 | 23 | applyAuthorStyles: true, 24 | 25 | checkInvariants: function() { 26 | if (!this.id) { 27 | console.error(this, 'is missing an id.'); 28 | } 29 | }, 30 | 31 | update_sec_nums: function(sec_num) { 32 | this.sec_num = sec_num + ''; 33 | var child_index = 1; 34 | // Assume there aren't any elements between spec-section levels. 35 | for (var child = this.firstChild; child; child = child.nextSibling) { 36 | if (child.localName == "spec-section") { 37 | child.update_sec_nums(this.sec_num + '.' + (child_index++)); 38 | } 39 | } 40 | }, 41 | 42 | sec_numChanged: function() { 43 | if (this.title_element) { 44 | this.title_element.setAttribute( 45 | 'data-bookmark-label', 46 | this.sec_num + ' ' + this.title_element.textContent); 47 | } 48 | }, 49 | 50 | attached: function() { 51 | var title_element = this.querySelector('h1'); 52 | if (title_element && title_element.parentElement == this) { 53 | this.title_element = title_element; 54 | } 55 | 56 | // async() lets the descendant elements upgrade; after which we 57 | // need to traverse them to assign paragraph numbers. 58 | this.async(this.numberParagraphChildren); 59 | }, 60 | 61 | numberParagraphChildren: function(rootElement, para_num_start) { 62 | var para_num = para_num_start || 1; 63 | for (var child = (rootElement || this).firstElementChild; child; 64 | child = child.nextElementSibling) { 65 | if (child instanceof SpecSectionElement) { 66 | return para_num; 67 | } else if (child instanceof HTMLParagraphElement && 68 | !child.classList.contains('cont')) { 69 | this.numberParagraph(para_num++, child); 70 | /* 71 | } else if (child instanceof SpecFunctionElement) { 72 | this.numberParagraph(para_num++, child); 73 | para_num = this.numberParagraphChildren(child, para_num); 74 | } else if (child instanceof CxxFunctionAttributeElement) { 75 | this.numberParagraph(para_num++, child); 76 | */ 77 | } 78 | } 79 | return para_num; 80 | }, 81 | 82 | numberParagraph: function(number, element) { 83 | var id = this.id + '.' + number; 84 | if (element.id) { 85 | console.warn('Paragraph already has id:', element); 86 | var anchor = document.createElement('a'); 87 | anchor.id = id; 88 | element.insertBefore(anchor, element.firstChild); 89 | } else { 90 | element.id = id; 91 | } 92 | element.setAttribute('para_num', number); 93 | } 94 | }) 95 | })(); 96 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/toc.html: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 19 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /publish/service_worker/FPWD-service-workers-20140501/assets/web-spec-framework/toc.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2014 Google Inc. All rights reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | (function() { 17 | Polymer('spec-toc', { 18 | // Hierarchy :: [{ elem: Element, title: H1, sections: Hierarchy }] 19 | sections: [], 20 | 21 | // Updated with the list of elements in the document each 22 | // time such an element is attached or detached. 23 | clauses: [], 24 | 25 | collectSections: function(root) { 26 | var sections = []; 27 | for (var child = root.firstElementChild; 28 | child; 29 | child = child.nextElementSibling) { 30 | if (child.tagName.toUpperCase() != 'SPEC-SECTION') { 31 | continue; 32 | } 33 | sections.push(this.collectSections(child)); 34 | } 35 | return {elem: root, 36 | title: root.querySelector('h1'), 37 | sections: sections}; 38 | }, 39 | 40 | clausesChanged: function() { 41 | this.sections = this.clauses.array().map(function(clause, index) { 42 | clause.set_clause_num(index + 1); 43 | return this.collectSections(clause); 44 | }, this); 45 | }, 46 | 47 | attached: function() { 48 | this.clauses = document.querySelectorAll('spec-clause'); 49 | } 50 | }) 51 | })(); 52 | -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": 114929 3 | , "contacts": ["siusin", "sideshowbarker"] 4 | , "repo-type": "rec-track" 5 | , "policy": "open" 6 | } 7 | -------------------------------------------------------------------------------- /why_not_appcache++.md: -------------------------------------------------------------------------------- 1 | **This is a legacy document and covers some of our early justifications** 2 | 3 |

Why Not AppCache++?

4 | 5 | You've read the [Explainer](explainer.md) and you're still wondering "why the heck do we need the Navigation Controller?" 6 | 7 | You've arrived at the right document -- not least of all because the other two aren't set up as explanations of the why, but more as expositions of the how. 8 | 9 | The indispensable Jake Archibald has written persuasively on the topic of why AppCache (as currently conceived and re-conceived in recent proposals) is insufficient to the task, and this document is (where it refines) a refinement of those points. You are encouraged to seek out his thinking independent of this tract -- a document that focuses on 3 main failings; in order from least-to-most problematic: 10 | 11 | - *Composition*: AppCache (and its recent iterations) deal with composition via pre-flattening: applications must create centrally managed lists of required resources, updating these lists every time the required set of items changes. This reflects the "chrome, not content" bias of AppCache and scales so poorly to distributed, large-scale server environments (multi-homed, load-balanced, and rolled out in stages) that it has already been identified as a central design failure by Facebook (among others). It remains unrepaired in both the latest AppCache drafts and proposed "AppCache v2" declarative forms. The larger failure is an inability to deal flexibly with mutually distrustful parties. AppCache provides no road to safe coordination between, e.g., font foundries and their customers in a cached scenario, depriving apps of creative flexibility easily afforded to native brethren or dooming their offline versions to a sub-standard experience. There's no standard contract for "here's how you cache off-domain resources without offending the other party" and AppCache is singularly unprepared to evolve to a world of lightweight collaboration. 12 | - *Misplaced Efficiency Arguments*: there is a deeply worrying strain of argument that pervades that debates around AppCache and Navigation Controller about the risks and rewards to be gained from the ability for developers to make "things that work offline" and the effort required to get there. The simplistic form of these views biases spec development not towards development of a coherent system for the co-operative creation of reliable systems, but towards the shortest thing to type. This misreads both our recent collective experience and the amount of data underlying the intuitions that precede this bias. Were the current systems powerful, scriptable, and lacking in short-form versions, we might observe libraries filling gaps in our current efforts. In such a scenario the general approach of Hussmanesque re-imagination of existing infrastructure to support clearly demonstrated needs -- as notably pursued by the Parkour team -- might hold sway. But this is not where we (collectively) are. Instead, the honest observer must concede a series of user-unpatchable failures, leading to a desolate landscape of powerless, forlorn web developers witnessing their native compatriots passing them in both fundamental power and library choice. Another variant of misplaced efficiency argument imagines (without data!) that current implementation state is the end of our collective creativity regarding threading, lifecycle management, and signal-fed optimization opportunities, despite the Navigation Controller spec being _explicitly_ designed to enable UA's to make (many) choices in nearly all corner cases which have performance impacts. 13 | - *Model Failure*: the "patch and pray" model of changes to the HTML 5 AppCache spec is excusable at first, second, and third. But given the _enormously_ long cycle times suffered by web developers attempting to adopt each new (fully-declarative, non-polyfillable) iteration, coupled with the intrinsic insecurity of not having direct programmatic control over caches and navigation dispositions, it becomes ever more difficult to write off the long trail of failure that follows AppCache everywhere it goes as "teething problems". Indeed, the latest `INTERCEPT` and (confus[ed|ing]) API additions speak to a spec in crisis. It knows it needs to hand power back to programmers, but has not created avenues to do this. Each new escape hatch lacks rigor and coherence, explaining little, if anything, about the levels above it while providing only momentary respite for the programmers who learn enough of AppCache to understand that they must pile _most_ of their applications into these misshapen outlets. It is time for a new approach that fundamentally empowers developers and treats performance as an (anticipated) implementation concern. 14 | 15 | Let's not beat around the bush: AppCache and its successors attempt a scenario-solving style of spec development in a problem domain its authors fundamentally did not understand. And it shows. 16 | 17 | Our efforts to enable pervasive offline have been long on self-assurance about what to do and light on evidence. Instead of admitting that we don't know the entire problem space, the needs of all classes of developers, and the architectural styles that they will employ based on their constraints, we have instead blundered forward based on assumptions -- assumptions about app architecture, about the commonality of the situation described by our loudest customers, and about the completeness and usability of our last best effort. 18 | 19 | Navigation Controllers represent a departure from hubris: by creating primitives that developers can explore (and yes, make mistakes with!) we create a space in which iteration can happen faster than the interoperable center of deployed browser features can expand. In sharp contrast to AppCache, Navigation Controllers require that we only expand the interoperable center once, powerfully, and then observe the winning patterns in order to discern what to standardize next. 20 | 21 | A key question for all web specs must always be "what is the role of a declarative form in this design?" The Parkour project has sought to reckon with this question regarding extensions to HTML elements in depth, at length, based on extensive library development and use as well as tremendous amounts of research and consultation with those most invested in delivering tools to web developers. As a result the project has created primitives that developers covet enormously: they explain existing behaviors and expand our collective horizons by decoupling the primitives from the declarative. These extensions, declarative and otherwise, have relied on strong evidence from a decade of library development, enabled in large part by giving web developers "too much" power to make tremendous messes. It is, however, these "messes" of unsemantic markup and impossibly-deep DOMs out of which our repairs have been informed. We can make efficient what we observe that developers (needlessly) do too much of. What we can't do, however, is anticipate everything everyone might do. 22 | 23 | A related question is often confused for the preceding query: _"what forms *must* be declarative?"_. In the case of the Navigation Controller, it seems that the answers are largely related to features it has not yet gained: 24 | 25 | - The ability to request bundles of permissions to elide runtime prompts 26 | - The ability to request installation with affordances (app icons, etc.) 27 | - System-enforced declarations of intent regarding relationships to other origins (e.g., CSP) and storage use 28 | 29 | None of these require that AppCache or its successors weigh in on questions of resource caching, navigation to URLs, or application initialization. What we have witnessed, therefore, appears to be a bait-and-switch: we have come to understand that some features must be declarative while choosing not to address them for the open web. 30 | 31 | That isn't to say that declarative forms aren't good and that we can't and won't evolve towards them. Indeed, "static routes" in Navigation Controllers are an early example of cow-path-paving: by creating a fully de-sugarable feature that has a terser form and a browser-fast-path implementation opportunity, Navigation Controllers are showing that it's possible to "evolve upward" to deliver both explanations for new features and improved performance over the long term for truly common patterns. This is the beginning of an evidence-based process of feature evolution that depends not on expanding the power of the overall system but observing states of nature and evolving to get better at the common cases. It's a method of evolution that AppCache can never hope to embody. 32 | 33 | The time for clearer air is now: we must focus first on providing declarative forms for what only the declarative _can_ do, leaving the rest to evidence, and where that is scant, to systems that provide the hope of collecting such evidence in the future. We have failed too much, too long to deceive ourselves further on these points. --------------------------------------------------------------------------------