-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathindex.js
128 lines (119 loc) · 4.61 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/* global MessageChannel Notification */
var assert = require('assert')
module.exports = serviceWorker
var events = serviceWorker.events = {
INSTALLED: 'sw:installed',
UPDATED: 'sw:updated',
REDUNDANT: 'sw:redundant',
POST_MESSAGE: 'sw:postMessage',
MESSAGE: 'sw:message',
SYNC: 'sw:sync',
NOTIFICATION_REQUEST: 'sw:notificationRequest',
ERROR: 'log:error'
}
function serviceWorker (name, opts) {
name = name || '/sw.js'
opts = opts || {}
assert.equal(typeof name, 'string', 'choo-service-worker: name should be type string')
assert.equal(typeof opts, 'object', 'choo-service-worker: opts should be type object')
return function (state, emitter) {
assert.equal(typeof state, 'object', 'choo-service-worker: state should be type object')
assert.equal(typeof emitter, 'object', 'choo-service-worker: emitter should be type object')
emitter.on(state.events.DOMCONTENTLOADED, function () {
opts = Object.assign({ scope: '/' }, opts)
// electron support
if (opts.electron) {
var path = require('path')
var url = require('url')
opts.scope = path.join(__dirname, opts.scope)
name = url.format({
pathname: path.join(__dirname, name.replace(/^\//, '')),
protocol: 'file:',
slashes: true
})
delete opts.electron
}
window.onmessage = function (event) {
emitter.emit(events.MESSAGE, { data: event.data, channel: 'window', port: null })
}
if (window.MessageChannel) {
var messageChannel = new MessageChannel()
messageChannel.port1.onmessage = function (event) {
emitter.emit(events.MESSAGE, { data: event.data, channel: 'messageChannel', port: 'port1' })
}
messageChannel.port2.onmessage = function (event) {
emitter.emit(events.MESSAGE, { data: event.data, channel: 'messageChannel', port: 'port2' })
}
}
emitter.on(events.NOTIFICATION_REQUEST, function (cb) {
Notification.requestPermission(function (result) {
if (typeof result === 'function') cb(result)
})
})
if (navigator.serviceWorker && navigator.onLine) {
navigator.serviceWorker.onmessage = function (event) {
emitter.emit(events.MESSAGE, { data: event.data, channel: 'navigator.serviceWorker', port: null })
}
navigator.serviceWorker.register(name, opts)
.then(function (registration) {
registration.onupdatefound = function () {
var installingWorker = registration.installing
installingWorker.onstatechange = function () {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
emitter.emit(events.UPDATED, registration)
} else {
emitter.emit(events.INSTALLED, registration)
}
} else if (installingWorker.state === 'redundant') {
emitter.emit(events.REDUNDANT, registration)
}
}
}
// Trigger the registration if it exists
if (registration.sync) getTags(registration)
}).catch(function (err) {
emitter.emit(events.ERROR, err)
})
// sw ready
navigator.serviceWorker.ready
.then(function (registration) {
new Promise(function (resolve) {
var worker = registration.active
if (worker.state === 'activated') {
resolve()
return
}
worker.addEventListener('statechange', resolve, { once: true })
emitter.on(events.POST_MESSAGE, function (message) {
worker.postMessage(message)
})
}).then(function () {
if (registration.navigationPreload) {
registration.navigationPreload.enable()
}
})
emitter.on(events.SYNC, function (tag) {
registration.sync.register(tag).then(function () {
return registration.sync.getTags()
}).then(function (tags) {
state.syncTags = tags
}).catch(function (err) {
emitter.emit(events.ERROR, err)
})
})
}).catch(function (err) {
emitter.emit(events.ERROR, err)
})
}
})
function getTags (registration) {
registration.sync.getTags()
.then(function (tags) {
state.syncTags = tags
}).catch(function (err) {
emitter.emit(events.ERROR, err)
})
}
}
}