Skip to content

Commit

Permalink
Implement amp-serviceworker-installation.
Browse files Browse the repository at this point in the history
Allows AMP pages to install a ServiceWorker to among other things
implement the pattern described in
https://medium.com/@cramforce/amps-and-websites-in-the-age-of-the-service-worker-8369841dc962
  • Loading branch information
cramforce committed Nov 20, 2015
1 parent b91fa41 commit e6199cf
Show file tree
Hide file tree
Showing 7 changed files with 261 additions and 0 deletions.
1 change: 1 addition & 0 deletions extensions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Current list of extended components:
| [`amp-fit-text`](amp-fit-text/amp-fit-text.md) | Expand or shrink font size to fit the content within the space given. |
| [`amp-font`](amp-font/amp-font.md) | Trigger and monitor the loading of custom fonts. |
| [`amp-iframe`](amp-iframe/amp-iframe.md) | Displays an iframe. |
| [`amp-install-serviceworker`](amp-install-serviceworker/amp-install-serviceworker.md) | Installs a ServiceWorker.
| [`amp-image-lightbox`](amp-image-lightbox/amp-image-lightbox.md) | Allows for a “image lightbox” or similar experience. |
| [`amp-instagram`](amp-instagram/amp-instagram.md) | Displays an instagram embed. |
| [`amp-lightbox`](amp-lightbox/amp-lightbox.md) | Allows for a “lightbox” or similar experience. |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Copyright 2015 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import {Layout} from '../../../src/layout';
import {parseUrl, assertHttpsUrl} from '../../../src/url';
import {getMode} from '../../../src/mode';

/**
* Implements custom element: <amp-install-serviceworker>
* for installation of ServiceWorkers owned by the publisher
* of the current page.
*/
class AmpServiceWorkerInstallation extends AMP.BaseElement {
/** @override */
buildCallback() {
const win = this.getWin();
if (!('serviceWorker' in win.navigator)) {
return;
}
const src = this.element.getAttribute('src');
assertHttpsUrl(src, this.element);

if (originMatches(win.location.href, src)) {
install(this.getWin(), src);
} else {
if (getMode().development) {
console./* OK */warn(
'Did not install ServiceWorker because it does not ' +
'match the current origin: ' + src);
}
}
}
}

/**
* Returns true if the 2 hrefs are on the same origin.
* @param {string} href1
* @param {string} href2
* return {boolean}
*/
function originMatches(href1, href2) {
return parseUrl(href1).origin == parseUrl(href2).origin;
}

/**
* Installs the service worker at src via direct service worker installation.
* @param {!Window} win
* @param {string} src
*/
function install(win, src) {
win.navigator.serviceWorker.register(src).then(function(registration) {
if (getMode().development) {
console./*OK*/info('ServiceWorker registration successful with scope: ',
registration.scope);
}
}).catch(function(e) {
console./*OK*/error('ServiceWorker registration failed:', e);
});
}

AMP.registerElement('amp-install-serviceworker',
AmpServiceWorkerInstallation);
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* Copyright 2015 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

require('../../../../build/all/v0/amp-install-serviceworker-0.1.max');
import {adopt} from '../../../../src/runtime';

adopt(window);

describe('amp-install-serviceworker', () => {
it('should install for same origin', () => {
const install = document.createElement('amp-install-serviceworker');
const implementation = install.implementation_;
expect(implementation).to.be.defined;
install.setAttribute('src', 'https://example.com/sw.js');
let calledSrc;
const p = new Promise(resolve => {});
implementation.getWin = () => {
return {
location: {
href: 'https://example.com/some/path'
},
navigator: {
serviceWorker: {
register: src => {
expect(calledSrc).to.be.undefined;
calledSrc = src;
return p;
}
}
}
};
};
implementation.buildCallback();
expect(calledSrc).to.equal('https://example.com/sw.js');
});

it('should be ok without service worker.', () => {
const install = document.createElement('amp-install-serviceworker');
const implementation = install.implementation_;
expect(implementation).to.be.defined;
install.setAttribute('src', 'https://example.com/sw.js');
implementation.getWin = () => {
return {
location: {
href: 'https://example.com/some/path'
},
navigator: {
}
};
};
implementation.buildCallback();
});

it('should do nothing with non-matching origins', () => {
const install = document.createElement('amp-install-serviceworker');
const implementation = install.implementation_;
expect(implementation).to.be.defined;
install.setAttribute('src', 'https://other-origin.com/sw.js');
let calledSrc;
const p = new Promise(resolve => {});
implementation.getWin = () => {
return {
location: {
href: 'https://example.com/some/path'
},
navigator: {
serviceWorker: {
register: src => {
calledSrc = src;
return p;
}
}
}
};
};
implementation.buildCallback();
expect(calledSrc).to.undefined;
});
});
48 changes: 48 additions & 0 deletions extensions/amp-install-serviceworker/amp-install-serviceworker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!---
Copyright 2015 The AMP HTML Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS-IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

### <a name="amp-install-serviceworker"></a> `amp-install-serviceworker`

The `amp-install-serviceworker` component allows installing a [ServiceWorker](http://www.html5rocks.com/en/tutorials/service-worker/introduction/) for the current page.

The idea here is that this ServiceWorker runs whenever the AMP file is served from the origin where you publish the AMP file. The ServiceWorker will not be loaded when the document is loaded from an AMP cache.

See [this article](https://medium.com/@cramforce/amps-and-websites-in-the-age-of-the-service-worker-8369841dc962) for how ServiceWorkers can help with making the AMP experience awesome with ServiceWorkers.

### Example

```html

<amp-install-serviceworker
src="https://www.your-domain.com/serviceworker.js"
layout="nodisplay"
</amp-install-serviceworker>

```

### Behavior

Registers the ServiceWorker given by the `src` attribute. If the current origin is different from the origin of the ServiceWorker, this custom element does nothing (Emits warning in development mode).

### Attributes

#### `src`

URL of the ServiceWorker to register.

#### `layout`

Must have the value `nodisplay`.
1 change: 1 addition & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ function buildExtensions(options) {
buildExtension('amp-list', '0.1', false, options);
buildExtension('amp-mustache', '0.1', false, options);
buildExtension('amp-pinterest', '0.1', true, options);
buildExtension('amp-install-serviceworker', '0.1', false, options);
/**
* @deprecated `amp-slides` is deprecated and will be deleted before 1.0.
* Please see {@link AmpCarousel} with `type=slides` attribute instead.
Expand Down
27 changes: 27 additions & 0 deletions test/manual/amp-install-serviceworker.amp.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!doctype html>
<html >
<head>
<meta charset="utf-8">
<title>amp-twitter</title>
<link rel="canonical" href="amps.html" >
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<script async custom-element="amp-twitter" src="../../dist/v0/amp-install-serviceworker-0.1.max.js"></script>
<style>
body {
max-width: 527px;
font-family: 'Questrial', Arial;
}
</style>
<style>body {opacity: 0}</style><noscript><style>body {opacity: 1}</style></noscript>
<script async src="../../dist/amp.js" development></script>
</head>
<body>
<h1>Should install a ServiceWorker if browser supports it.</h1>
<amp-install-serviceworker
src="./test-sw.js"
layout="nodisplay">
</amp-install-serviceworker>
</body>
</html>


17 changes: 17 additions & 0 deletions test/manual/test-sw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Copyright 2015 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

console./*OK*/info('ServiceWorker loaded.');

0 comments on commit e6199cf

Please sign in to comment.