Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Communication enhancements #13

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 88 additions & 10 deletions dist/offliner-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,21 +79,78 @@
* @return {Promise} A promise resolving if the installation success.
*/
install: function () {
this._installMessageHandlers();
if (!('serviceWorker' in navigator)) {
return Promise.reject(new Error('serviceworkers-not-supported'));
}

return navigator.serviceWorker.register(workerURL, {
scope: root
});
}).then(function (registration) {
return this.connect().then(function () {
return registration;
});
}.bind(this));
},

/**
* If you are using offliner as a serviceworkerware middleware, instead
* of calling {{#crossLink OfflinerClient/install:method}}{{/crossLink}},
* call `connect()` to avoid registering the worker.
* Keeps the promise of connect.
*
* @property _connecting
* @type Promise
* @private
*/
_connecting: null,

/**
* Connects the client with offliner allowing the client to control offliner
* and receive events.
*
* @method connect
* @return {Promise} A promise resolving once connection has been stablished
* with the worker and communication is possible.
*/
connect: function () {
this._installMessageHandlers();
if (!this._connecting) { this._connecting = this._connect(); }
return this._connecting;
},

/**
* The actual implementation for {{#crossLink "connect:method"}}{{/crossLink}}
*
* @method _connect
* @return {Promise} A promise resolving once connection has been stablished
* with the worker and communication is possible.
* @private
*/
_connect: function () {
if (!('serviceWorker' in navigator)) {
return Promise.reject(new Error('serviceworkers-not-supported'));
}

var installMessageHandlers = this._installMessageHandlers.bind(this);
var checkForActivationPending = this._checkForActivationPending.bind(this);
return new Promise(function (fulfill, reject) {
navigator.serviceWorker.getRegistration(root).then(function (registration) {
if (registration.active) {
installMessageHandlers();
checkForActivationPending();
return fulfill();
}

var installingWorker = registration.installing;
if (!installingWorker) {
return reject(new Error('impossible-to-connect'));
}

installingWorker.onstatechange = function () {
if (installingWorker.state === 'installed') {
installMessageHandlers();
checkForActivationPending();
fulfill();
}
};
});
});
},

/**
Expand All @@ -117,7 +174,7 @@
* @method update
* @return {Promise} If the update process is successful, the promise will
* resolve to a new version and an
* {{#crossLink OfflinerClient/activationPending:event}}{{/crossLink}}
* {{#crossLink "OfflinerClient/activationPending:event"}}{{/crossLink}}
* will be triggered. If the update is not needed, the promise will be
* rejected with `no-update-needed` reason.
*/
Expand Down Expand Up @@ -145,6 +202,7 @@
* @param type {String} The type of the events selecting the listeners to
* be run.
* @param evt {Object} The event contents.
* @private
*/
_runListeners: function (type, evt) {
var listeners = this._eventListeners[type] || [];
Expand All @@ -160,6 +218,7 @@
* and the client code.
*
* @method _installMessageHandlers
* @private
*/
_installMessageHandlers: function installMessageHandlers() {
var that = this;
Expand All @@ -185,14 +244,28 @@
},

/**
* Discriminates between {{#crossLink OfflinerClient/xpromise:event}}{{/crossLink}}
* Make offliner to check for pending activations and dispatch
* {{#crossLink "OfflinerClient/activationPending:event"}}{{/crossLink}}
* if so.
*
* @method _checkForActivationPending
* @private
*/
_checkForActivationPending: function () {
// TODO: should we add a prefix for offliner messages?
this._send({ type: 'checkForActivationPending' });
},

/**
* Discriminates between {{#crossLink "OfflinerClient/xpromise:event"}}{{/crossLink}}
* events which are treated in a special way and the rest of the events that
* simply trigger the default dispatching algorithm.
*
* @method _handleMessage
* @param offlinerType {String} The type of the message without the
* `offliner:` prefix.
* @param msg {Any} The event.
* @private
*/
_handleMessage: function (offlinerType, msg) {
var sw = navigator.serviceWorker;
Expand All @@ -211,6 +284,7 @@
* @param willBeThis {Object} The context object `this` which the function
* will be called with.
* @return `true` if the listener registration already exists.
* @private
*/
_has: function (type, handler, willBeThis) {
var listeners = this._eventListeners[type] || [];
Expand All @@ -233,6 +307,7 @@
* the implementation to run.
* @return {Promise} A promise delegating its implementation in some code
* running in a worker.
* @private
*/
_xpromise: function (order) {
return new Promise(function (accept, reject) {
Expand All @@ -253,16 +328,18 @@

/**
* Sends a message to the worker.
*
* @method _send
* @param msg {Any} The message to be sent.
* @private
*/
_send: function (msg) {
navigator.serviceWorker.getRegistration()
navigator.serviceWorker.getRegistration(root)
.then(function (registration) {
if (!registration || !registration.active) {
// TODO: Wait for the service worker to be active and try to
// resend.
warn('Not service worker active right now.');
console.warn('Not service worker active right now.');
}
else {
return registration.active.postMessage(msg);
Expand All @@ -276,6 +353,7 @@
*
* @method _resolveCrossPromise
* @param msg {Object} An object with the proper data to resolve a xpromise.
* @private
*/
_resolveCrossPromise: function (msg) {
var implementation = this._xpromises[msg.id];
Expand Down
2 changes: 1 addition & 1 deletion dist/offliner-client.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 24 additions & 5 deletions dist/offliner.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
* @method standalone
* @throws {Error} offliner throws when trying to install it in standalone
* mode if it was already used as middleware by calling
* {{#crossLink Offliner/asMiddleware:method}}{{/crossLink}}.
* {{#crossLink "Offliner/asMiddleware:method"}}{{/crossLink}}.
*/
Offliner.prototype.standalone = function () {
if (this._isMiddleware) {
Expand Down Expand Up @@ -185,7 +185,7 @@
* @method asMiddleware
* @return {Object} A serviceworkerware middleware.
* @throws {Error} offliner will throw if you try to use it as middleware
* after calling {{#crossLink Offliner/standalone:method}}{{/crossLink}}.
* after calling {{#crossLink "Offliner/standalone:method"}}{{/crossLink}}.
*/
Offliner.prototype.asMiddleware = function () {
if (this._isStarted) {
Expand Down Expand Up @@ -228,6 +228,9 @@
case 'xpromise':
this._receiveCrossPromise(msg.id, msg.order);
break;
case 'checkForActivationPending':
this._checkForActivationPending();
break;
default:
warn('Message not recognized:', msg);
break;
Expand Down Expand Up @@ -263,6 +266,21 @@
}
};

/**
* Check if there is an activation pending. If so, offliner dispatches an
* activation pending request.
*
* @method _checkForActivationPending
* @private
*/
Offliner.prototype._checkForActivationPending = function () {
this.get('activation-pending').then(function (isActivationPending) {
if (isActivationPending) {
this._sendActivationPending();
}
}.bind(this));
};

/**
* Resolves a cross promise.
*
Expand Down Expand Up @@ -461,6 +479,7 @@
*
* @method _sendActivationDone
* @private
* @for Offliner
*/
Offliner.prototype._sendActivationDone = function () {
this._broadcastMessage({ type: 'activationDone' });
Expand All @@ -480,7 +499,7 @@
/**
* Broadcast a message in the clients. The method will add the `offliner:`
* prefix to the type of the events but this is stripped out automatically by
* the {{#crossLink OfflinerClient/_installMessageHandlers:method}}{{/crossLink}}
* the {{#crossLink "OfflinerClient/_installMessageHandlers:method"}}{{/crossLink}}
* client side.
*
* @method _broadcastMessage
Expand Down Expand Up @@ -768,7 +787,7 @@
*/

/**
* Normalizes a resource not following the {{#crossLink Resource}}
* Normalizes a resource not following the {{#crossLink "Resource"}}
* {{/crossLink}} convention.
*
* @method normalize
Expand Down Expand Up @@ -798,7 +817,7 @@
}

/**
* Register a {{#crossLink Fetcher}}{{/crossLink}}. The fetcher will be used
* Register a {{#crossLink "Fetcher"}}{{/crossLink}}. The fetcher will be used
* to retrieve the resources of the fetcher's type.
*
* @method use
Expand Down
Loading