Skip to content

Commit fe1a2dd

Browse files
committed
Merge pull request #954 from cramforce/sw-installation
Implement amp-install-serviceworker
2 parents db76a6f + e6199cf commit fe1a2dd

File tree

7 files changed

+261
-0
lines changed

7 files changed

+261
-0
lines changed

extensions/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Current list of extended components:
2424
| [`amp-fit-text`](amp-fit-text/amp-fit-text.md) | Expand or shrink font size to fit the content within the space given. |
2525
| [`amp-font`](amp-font/amp-font.md) | Trigger and monitor the loading of custom fonts. |
2626
| [`amp-iframe`](amp-iframe/amp-iframe.md) | Displays an iframe. |
27+
| [`amp-install-serviceworker`](amp-install-serviceworker/amp-install-serviceworker.md) | Installs a ServiceWorker.
2728
| [`amp-image-lightbox`](amp-image-lightbox/amp-image-lightbox.md) | Allows for a “image lightbox” or similar experience. |
2829
| [`amp-instagram`](amp-instagram/amp-instagram.md) | Displays an instagram embed. |
2930
| [`amp-lightbox`](amp-lightbox/amp-lightbox.md) | Allows for a “lightbox” or similar experience. |
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* Copyright 2015 The AMP HTML Authors. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS-IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {Layout} from '../../../src/layout';
18+
import {parseUrl, assertHttpsUrl} from '../../../src/url';
19+
import {getMode} from '../../../src/mode';
20+
21+
/**
22+
* Implements custom element: <amp-install-serviceworker>
23+
* for installation of ServiceWorkers owned by the publisher
24+
* of the current page.
25+
*/
26+
class AmpServiceWorkerInstallation extends AMP.BaseElement {
27+
/** @override */
28+
buildCallback() {
29+
const win = this.getWin();
30+
if (!('serviceWorker' in win.navigator)) {
31+
return;
32+
}
33+
const src = this.element.getAttribute('src');
34+
assertHttpsUrl(src, this.element);
35+
36+
if (originMatches(win.location.href, src)) {
37+
install(this.getWin(), src);
38+
} else {
39+
if (getMode().development) {
40+
console./* OK */warn(
41+
'Did not install ServiceWorker because it does not ' +
42+
'match the current origin: ' + src);
43+
}
44+
}
45+
}
46+
}
47+
48+
/**
49+
* Returns true if the 2 hrefs are on the same origin.
50+
* @param {string} href1
51+
* @param {string} href2
52+
* return {boolean}
53+
*/
54+
function originMatches(href1, href2) {
55+
return parseUrl(href1).origin == parseUrl(href2).origin;
56+
}
57+
58+
/**
59+
* Installs the service worker at src via direct service worker installation.
60+
* @param {!Window} win
61+
* @param {string} src
62+
*/
63+
function install(win, src) {
64+
win.navigator.serviceWorker.register(src).then(function(registration) {
65+
if (getMode().development) {
66+
console./*OK*/info('ServiceWorker registration successful with scope: ',
67+
registration.scope);
68+
}
69+
}).catch(function(e) {
70+
console./*OK*/error('ServiceWorker registration failed:', e);
71+
});
72+
}
73+
74+
AMP.registerElement('amp-install-serviceworker',
75+
AmpServiceWorkerInstallation);
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* Copyright 2015 The AMP HTML Authors. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS-IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
require('../../../../build/all/v0/amp-install-serviceworker-0.1.max');
18+
import {adopt} from '../../../../src/runtime';
19+
20+
adopt(window);
21+
22+
describe('amp-install-serviceworker', () => {
23+
it('should install for same origin', () => {
24+
const install = document.createElement('amp-install-serviceworker');
25+
const implementation = install.implementation_;
26+
expect(implementation).to.be.defined;
27+
install.setAttribute('src', 'https://example.com/sw.js');
28+
let calledSrc;
29+
const p = new Promise(resolve => {});
30+
implementation.getWin = () => {
31+
return {
32+
location: {
33+
href: 'https://example.com/some/path'
34+
},
35+
navigator: {
36+
serviceWorker: {
37+
register: src => {
38+
expect(calledSrc).to.be.undefined;
39+
calledSrc = src;
40+
return p;
41+
}
42+
}
43+
}
44+
};
45+
};
46+
implementation.buildCallback();
47+
expect(calledSrc).to.equal('https://example.com/sw.js');
48+
});
49+
50+
it('should be ok without service worker.', () => {
51+
const install = document.createElement('amp-install-serviceworker');
52+
const implementation = install.implementation_;
53+
expect(implementation).to.be.defined;
54+
install.setAttribute('src', 'https://example.com/sw.js');
55+
implementation.getWin = () => {
56+
return {
57+
location: {
58+
href: 'https://example.com/some/path'
59+
},
60+
navigator: {
61+
}
62+
};
63+
};
64+
implementation.buildCallback();
65+
});
66+
67+
it('should do nothing with non-matching origins', () => {
68+
const install = document.createElement('amp-install-serviceworker');
69+
const implementation = install.implementation_;
70+
expect(implementation).to.be.defined;
71+
install.setAttribute('src', 'https://other-origin.com/sw.js');
72+
let calledSrc;
73+
const p = new Promise(resolve => {});
74+
implementation.getWin = () => {
75+
return {
76+
location: {
77+
href: 'https://example.com/some/path'
78+
},
79+
navigator: {
80+
serviceWorker: {
81+
register: src => {
82+
calledSrc = src;
83+
return p;
84+
}
85+
}
86+
}
87+
};
88+
};
89+
implementation.buildCallback();
90+
expect(calledSrc).to.undefined;
91+
});
92+
});
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<!---
2+
Copyright 2015 The AMP HTML Authors. All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS-IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
17+
### <a name="amp-install-serviceworker"></a> `amp-install-serviceworker`
18+
19+
The `amp-install-serviceworker` component allows installing a [ServiceWorker](http://www.html5rocks.com/en/tutorials/service-worker/introduction/) for the current page.
20+
21+
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.
22+
23+
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.
24+
25+
### Example
26+
27+
```html
28+
29+
<amp-install-serviceworker
30+
src="https://www.your-domain.com/serviceworker.js"
31+
layout="nodisplay"
32+
</amp-install-serviceworker>
33+
34+
```
35+
36+
### Behavior
37+
38+
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).
39+
40+
### Attributes
41+
42+
#### `src`
43+
44+
URL of the ServiceWorker to register.
45+
46+
#### `layout`
47+
48+
Must have the value `nodisplay`.

gulpfile.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ function buildExtensions(options) {
7777
buildExtension('amp-list', '0.1', false, options);
7878
buildExtension('amp-mustache', '0.1', false, options);
7979
buildExtension('amp-pinterest', '0.1', true, options);
80+
buildExtension('amp-install-serviceworker', '0.1', false, options);
8081
/**
8182
* @deprecated `amp-slides` is deprecated and will be deleted before 1.0.
8283
* Please see {@link AmpCarousel} with `type=slides` attribute instead.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!doctype html>
2+
<html >
3+
<head>
4+
<meta charset="utf-8">
5+
<title>amp-twitter</title>
6+
<link rel="canonical" href="amps.html" >
7+
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
8+
<script async custom-element="amp-twitter" src="../../dist/v0/amp-install-serviceworker-0.1.max.js"></script>
9+
<style>
10+
body {
11+
max-width: 527px;
12+
font-family: 'Questrial', Arial;
13+
}
14+
</style>
15+
<style>body {opacity: 0}</style><noscript><style>body {opacity: 1}</style></noscript>
16+
<script async src="../../dist/amp.js" development></script>
17+
</head>
18+
<body>
19+
<h1>Should install a ServiceWorker if browser supports it.</h1>
20+
<amp-install-serviceworker
21+
src="./test-sw.js"
22+
layout="nodisplay">
23+
</amp-install-serviceworker>
24+
</body>
25+
</html>
26+
27+

test/manual/test-sw.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright 2015 The AMP HTML Authors. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS-IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
console./*OK*/info('ServiceWorker loaded.');

0 commit comments

Comments
 (0)