| Index: polymer_1.0.4/bower_components/platinum-push-messaging/platinum-push-messaging.html
|
| diff --git a/polymer_1.0.4/bower_components/platinum-push-messaging/platinum-push-messaging.html b/polymer_1.0.4/bower_components/platinum-push-messaging/platinum-push-messaging.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7a43a73bd7eb949fdfac9e5ccf3a4f7e88e8fdff
|
| --- /dev/null
|
| +++ b/polymer_1.0.4/bower_components/platinum-push-messaging/platinum-push-messaging.html
|
| @@ -0,0 +1,427 @@
|
| +<!--
|
| +@license
|
| +Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
|
| +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| +Code distributed by Google as part of the polymer project is also
|
| +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| +-->
|
| +<link rel="import" href="../polymer/polymer.html">
|
| +
|
| +<script>
|
| + (function() {
|
| + 'use strict';
|
| + // TODO: Doesn't work for IE or Safari, and the usual
|
| + // document.getElementsByTagName('script') workaround seems to be broken by
|
| + // HTML imports. Not important for now as neither of those browsers support
|
| + // service worker yet.
|
| + var currentScript = document.currentScript.baseURI;
|
| +
|
| + var SCOPE = new URL('./$$platinum-push-messaging$$/', currentScript).href;
|
| + var WORKER_URL = new URL('./service-worker.js', currentScript).href;
|
| +
|
| + var BASE_URL = new URL('./', document.location.href).href;
|
| +
|
| + var SUPPORTED = 'serviceWorker' in navigator &&
|
| + 'PushManager' in window &&
|
| + 'Notification' in window;
|
| +
|
| + /**
|
| + * @const {Number} The desired version of the service worker to use. This is
|
| + * not strictly tied to anything except that it should be changed whenever
|
| + * a breaking change is made to the service worker code.
|
| + */
|
| + var VERSION = 1;
|
| +
|
| + // This allows us to use the PushSubscription attribute type in browsers
|
| + // where it is not defined.
|
| + if (!('PushSubscription' in window)) {
|
| + window.PushSubscription = {};
|
| + }
|
| +
|
| + /**
|
| + * `<platinum-push-messaging>` sets up a [push messaging][1] subscription
|
| + * and allows you to define what happens when a push message is received.
|
| + *
|
| + * The element can be placed anywhere, but should only be used once in a
|
| + * page. If there are multiple occurrences, only one will be active.
|
| + *
|
| + * # Requirements
|
| + * Push messaging is currently only available in Google Chrome, which
|
| + * requires you to configure Google Cloud Messaging. Chrome will check that
|
| + * your page links to a manifest file that contains a `gcm_sender_id` field.
|
| + * You can find full details of how to set all of this up in the [HTML5
|
| + * Rocks guide to push notifications][1].
|
| + *
|
| + * # Notifcation details
|
| + * The data for how a notification should be displayed can come from one of
|
| + * three places.
|
| + *
|
| + * Firstly, you can specify a URL from which to fetch the message data.
|
| + * ```
|
| + * <platinum-push-messaging
|
| + * message-url="notification-data.json">
|
| + * </platinum-push-messaging>
|
| + * ```
|
| + *
|
| + * The second way is to send the message data in the body of
|
| + * the push message from your server. In this case you do not need to
|
| + * configure anything in your page:
|
| + * ```
|
| + * <platinum-push-messaging></platinum-push-messaging>
|
| + * ```
|
| + * **Note that this method is not currently supported by any browser**. It
|
| + * is, however, defined in the
|
| + * [draft W3C specification](http://w3c.github.io/push-api/#the-push-event)
|
| + * and this element should use that data when it is implemented in the
|
| + * future.
|
| + *
|
| + * If a message-url is provided then the message body will be ignored in
|
| + * favor of the first method.
|
| + *
|
| + * Thirdly, you can manually define the attributes on the element:
|
| + * ```
|
| + * <platinum-push-messaging
|
| + * title="Application updated"
|
| + * message="The application was updated in the background"
|
| + * icon-url="icon.png"
|
| + * click-url="notification.html">
|
| + * </platinum-push-messaging>
|
| + * ```
|
| + * These values will also be used as defaults if one of the other methods
|
| + * does not provide a value for that property.
|
| + *
|
| + * # Testing
|
| + * If you have set up Google Cloud Messaging then you can send push messages
|
| + * to your browser by following the guide in the [GCM documentation][2].
|
| + *
|
| + * However, for quick client testing there are two options. You can use the
|
| + * `testPush` method, which allows you to simulate a push message that
|
| + * includes a payload.
|
| + *
|
| + * Or, at a lower level, you can open up chrome://serviceworker-internals in
|
| + * Chrome and use the 'Push' button for the service worker corresponding to
|
| + * your app.
|
| + *
|
| + * [1]: http://updates.html5rocks.com/2015/03/push-notificatons-on-the-open-web
|
| + * [2]: https://developer.android.com/google/gcm/http.html
|
| + *
|
| + * @demo demo/
|
| + */
|
| + Polymer({
|
| + is: 'platinum-push-messaging',
|
| +
|
| + properties: {
|
| +
|
| + /**
|
| + * Indicates whether the Push and Notification APIs are supported by
|
| + * this browser.
|
| + */
|
| + supported: {
|
| + readOnly: true,
|
| + type: Boolean,
|
| + value: SUPPORTED
|
| + },
|
| +
|
| + /**
|
| + * The details of the current push subscription, if any.
|
| + */
|
| + subscription: {
|
| + readOnly: true,
|
| + type: PushSubscription,
|
| + notify: true,
|
| + },
|
| +
|
| + /**
|
| + * Indicates the status of the element. If true, push messages will be
|
| + * received.
|
| + */
|
| + enabled: {
|
| + readOnly: true,
|
| + type: Boolean,
|
| + notify: true,
|
| + value: false
|
| + },
|
| +
|
| +
|
| + /**
|
| + * A URL from which message information can be retrieved.
|
| + *
|
| + * When a push event happens that does not contain a message body this
|
| + * URL will be fetched. The URL is expected to be for a JSON document in
|
| + * the format:
|
| + * ```
|
| + * {
|
| + * "title": "The title for the notification",
|
| + * "body": "The message to display in the notification",
|
| + * "url": "The URL to display when the notification is clicked",
|
| + * "icon": "The URL of an icon to display with the notification",
|
| + * "tag": "An identifier that determines which notifications can be displayed at the same time"
|
| + * }
|
| + * ```
|
| + */
|
| + messageUrl: String,
|
| +
|
| + /**
|
| + * A default notification title.
|
| + */
|
| + title: String,
|
| +
|
| + /**
|
| + * A default notification message.
|
| + */
|
| + message: String,
|
| +
|
| + /**
|
| + * A default icon for notifications.
|
| + */
|
| + iconUrl: String,
|
| +
|
| + /**
|
| + * A default URL to display when a notification is clicked.
|
| + */
|
| + clickUrl: {
|
| + type: String,
|
| + value: document.location.href
|
| + },
|
| +
|
| + /**
|
| + * A default tag for the notifications that will be generated by
|
| + * this element. Notifications with the same tag will overwrite one
|
| + * another, so that only one will be shown at once.
|
| + */
|
| + tag: String
|
| + },
|
| +
|
| + /**
|
| + * Fired when a notification is clicked that had the current page as the
|
| + * click URL.
|
| + *
|
| + * @event platinum-push-messaging-click
|
| + * @param {Object} The push message data used to create the notification
|
| + */
|
| +
|
| + /**
|
| + * Fired when a push message is received but no notification is shown.
|
| + * This happens when the click URL is for this page and the page is
|
| + * visible to the user on the screen.
|
| + *
|
| + * @event platinum-push-messaging-push
|
| + * @param {Object} The push message data that was received
|
| + */
|
| +
|
| + /**
|
| + * Fired when an error occurs while enabling or disabling notifications
|
| + *
|
| + * @event platinum-push-messaging-error
|
| + * @param {String} The error message
|
| + */
|
| +
|
| + /**
|
| + * Returns a promise which will resolve to the registration object
|
| + * associated with our current service worker.
|
| + *
|
| + * @return {Promise<ServiceWorkerRegistration>}
|
| + */
|
| + _getRegistration: function() {
|
| + return navigator.serviceWorker.getRegistration(SCOPE);
|
| + },
|
| +
|
| + /**
|
| + * Returns a promise that will resolve when the given registration becomes
|
| + * active.
|
| + *
|
| + * @param registration {ServiceWorkerRegistration}
|
| + * @return {Promise<undefined>}
|
| + */
|
| + _registrationReady: function(registration) {
|
| + if (registration.active) {
|
| + return Promise.resolve();
|
| + }
|
| +
|
| + var serviceWorker = registration.installing || registration.waiting;
|
| +
|
| + return new Promise(function(resolve, reject) {
|
| + // Because the Promise function is called on next tick there is a
|
| + // small chance that the worker became active already.
|
| + if (serviceWorker.state === 'activated') {
|
| + resolve();
|
| + }
|
| + var listener = function(event) {
|
| + if (serviceWorker.state === 'activated') {
|
| + resolve();
|
| + } else if (serviceWorker.state === 'redundant') {
|
| + reject(new Error('Worker became redundant'));
|
| + } else {
|
| + return;
|
| + }
|
| + serviceWorker.removeEventListener('statechange', listener);
|
| + };
|
| + serviceWorker.addEventListener('statechange', listener);
|
| + });
|
| + },
|
| +
|
| + /**
|
| + * Event handler for the `message` event.
|
| + *
|
| + * @param event {MessageEvent}
|
| + */
|
| + _messageHandler: function(event) {
|
| + if (event.data && event.data.source === SCOPE) {
|
| + switch(event.data.type) {
|
| + case 'push':
|
| + this.fire('platinum-push-messaging-push', event.data);
|
| + break;
|
| + case 'click':
|
| + this.fire('platinum-push-messaging-click', event.data);
|
| + break;
|
| + }
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Takes an options object and creates a stable JSON serialization of it.
|
| + * This naive algorithm will only work if the object contains only
|
| + * non-nested properties.
|
| + *
|
| + * @param options {Object.<String, ?(String|Number|Boolean)>}
|
| + * @return String
|
| + */
|
| + _serializeOptions: function(options) {
|
| + var props = Object.keys(options);
|
| + props.sort();
|
| + var parts = props.filter(function(propName) {
|
| + return !!options[propName];
|
| + }).map(function(propName) {
|
| + return JSON.stringify(propName) + ':' + JSON.stringify(options[propName]);
|
| + });
|
| + return '{' + parts.join(',') + '}';
|
| + },
|
| +
|
| + /**
|
| + * Determine the URL of the worker based on the currently set parameters
|
| + *
|
| + * @return String the URL
|
| + */
|
| + _getWorkerURL: function() {
|
| + var options = this._serializeOptions({
|
| + tag: this.tag,
|
| + messageUrl: this.messageUrl,
|
| + title: this.title,
|
| + message: this.message,
|
| + iconUrl: this.iconUrl,
|
| + clickUrl: this.clickUrl,
|
| + version: VERSION,
|
| + baseUrl: BASE_URL
|
| + });
|
| +
|
| + return WORKER_URL + '?' + options;
|
| + },
|
| +
|
| + /**
|
| + * Update the subscription property, but only if the value has changed.
|
| + * This prevents triggering the subscription-changed event twice on page
|
| + * load.
|
| + */
|
| + _updateSubscription: function(subscription) {
|
| + if (JSON.stringify(subscription) !== JSON.stringify(this.subscription)) {
|
| + this._setSubscription(subscription);
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Programmatically trigger a push message
|
| + *
|
| + * @param message {Object} the message payload
|
| + */
|
| + testPush: function(message) {
|
| + this._getRegistration().then(function(registration) {
|
| + registration.active.postMessage({
|
| + type: 'test-push',
|
| + message: message
|
| + });
|
| + });
|
| + },
|
| +
|
| + /**
|
| + * Request push messaging to be enabled.
|
| + *
|
| + * @return {Promise<undefined>}
|
| + */
|
| + enable: function() {
|
| + if (!this.supported) {
|
| + this.fire('platinum-push-messaging-error', 'Your browser does not support push notifications');
|
| + return Promise.resolve();
|
| + }
|
| +
|
| + return navigator.serviceWorker.register(this._getWorkerURL(), {scope: SCOPE}).then(function(registration) {
|
| + return this._registrationReady(registration).then(function() {
|
| + return registration.pushManager.subscribe({userVisibleOnly: true});
|
| + });
|
| + }.bind(this)).then(function(subscription) {
|
| + this._updateSubscription(subscription);
|
| + this._setEnabled(true);
|
| + }.bind(this)).catch(function(error) {
|
| + this.fire('platinum-push-messaging-error', error.message || error);
|
| + }.bind(this));
|
| + },
|
| +
|
| + /**
|
| + * Request push messaging to be disabled.
|
| + *
|
| + * @return {Promise<undefined>}
|
| + */
|
| + disable: function() {
|
| + if (!this.supported) {
|
| + return Promise.resolve();
|
| + }
|
| +
|
| + return this._getRegistration().then(function(registration) {
|
| + if (!registration) {
|
| + return;
|
| + }
|
| + return registration.pushManager.getSubscription().then(function(subscription) {
|
| + if (subscription) {
|
| + return subscription.unsubscribe();
|
| + }
|
| + }).then(function() {
|
| + return registration.unregister();
|
| + }).then(function() {
|
| + this._updateSubscription();
|
| + this._setEnabled(false);
|
| + }.bind(this)).catch(function(error) {
|
| + this.fire('platinum-push-messaging-error', error.message || error);
|
| + }.bind(this));
|
| + }.bind(this));
|
| + },
|
| +
|
| + ready: function() {
|
| + if (this.supported) {
|
| + var handler = this._messageHandler.bind(this);
|
| + // NOTE: We add the event listener twice because the specced and
|
| + // implemented behaviors do not match. In Chrome 42, messages are
|
| + // received on window. In the current spec they are supposed to be
|
| + // received on navigator.serviceWorker.
|
| + // TODO: Remove the non-spec code in the future.
|
| + window.addEventListener('message', handler);
|
| + navigator.serviceWorker.addEventListener('message', handler);
|
| +
|
| + this._getRegistration().then(function(registration) {
|
| + if (!registration) {
|
| + return;
|
| + }
|
| + if (registration.active && registration.active.scriptURL !== this._getWorkerURL()) {
|
| + // We have an existing worker in this scope, but it is out of date
|
| + return this.enable();
|
| + }
|
| + return registration.pushManager.getSubscription().then(function(subscription) {
|
| + this._updateSubscription(subscription);
|
| + this._setEnabled(true);
|
| + }.bind(this));
|
| + }.bind(this));
|
| + }
|
| + }
|
| + });
|
| + })();
|
| +</script>
|
|
|