Exemple #1
0
        public async Task AppendToServiceWorkerScript(StringBuilder sw, PwaOptions options, HttpContext context, IUrlHelper urlHelper)
        {
            #region ClientMessageBus

            sw.Append("var idb;");
            sw.Append("if(self.indexedDB) { ");
            sw.Append("idb = self.indexedDB; ");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('IndexedDB is supported');");
            }
            sw.Append("} ");



            sw.Append("function sendMessage(msg) {");

            sw.Append("if ('BroadcastChannel' in self) {");

            sw.Append("const channel = new BroadcastChannel('app-channel');");
            sw.Append("channel.postMessage(msg);");

            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('sent message to client');");
            }

            sw.Append("} else {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('message not sent to client because BroadcastChannel not supported by the browser');");
            }
            sw.Append("} "); //endif broadcast channel
            sw.Append("} "); //end send message


            sw.Append("var messageListBuilder = function() {");
            sw.Append("var priv;");

            sw.Append("function build() {");

            sw.Append("if(priv) {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('returning ready function');");
            }

            sw.Append("return;");

            sw.Append("} else {");

            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('building messagelist function');");
            }

            sw.Append("priv = {");

            sw.Append("addMessage : function(msg) {");

            sw.Append("if(idb) {");

            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('add message');");
            }

            sw.Append("var request = idb.open('sw_DB', 1);");

            sw.Append("request.onsuccess = function(event) {");

            sw.Append("var db = event.target.result;");
            sw.Append("var transaction = db.transaction('clientmessages', 'readwrite');");

            sw.Append("transaction.onsuccess = function(event) {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('IndexDB transaction success');");
            }

            sw.Append("}; ");//endtransaction.success

            sw.Append("var msgStore = transaction.objectStore('clientmessages');");
            sw.Append("var db_op_req = msgStore.add(msg);");

            sw.Append("db_op_req.onsuccess = function(event) {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log(event);");
            }

            sw.Append("}; "); //end db_op_req onsucess

            sw.Append("}; "); //end request onsuccess

            sw.Append("request.onupgradeneeded = function(event) {");
            sw.Append("var db = event.target.result;");
            sw.Append("var store = db.createObjectStore('clientmessages', {keyPath:'id'});");
            sw.Append("}; ");// end onupgraded

            sw.Append("} else {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('failed to add message because IndexedDB not suppported in this browser');");
            }
            sw.Append("} ");

            sw.Append("},"); //end add message

            sw.Append("iterate: function(f) {");

            sw.Append("if(idb) {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('iterate message');");
            }
            sw.Append("var request = idb.open('sw_DB', 1);");

            sw.Append("request.onupgradeneeded = function(event) {");
            sw.Append("var db = event.target.result;");
            sw.Append("var store = db.createObjectStore('clientmessages', {keyPath : 'id'});");
            sw.Append("}; ");// end onupgraded


            sw.Append("request.onsuccess = function(event) {");

            sw.Append("var db = event.target.result; ");

            sw.Append("var transaction = db.transaction('clientmessages', 'readwrite');");
            sw.Append("transaction.onsuccess = function(event) {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('IndexDb transaction success');");
            }

            sw.Append("}; ");//endtransaction.success

            sw.Append("var msgStore = transaction.objectStore('clientmessages');");

            //get all messages and send to client
            sw.Append("msgStore.getAll().onsuccess = function(event) {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('get all messages');");
                sw.Append("console.log(event.target.result);");
            }

            sw.Append("var list = event.target.result;");

            sw.Append("list.forEach(function(msg) {");
            sw.Append("f(msg);");
            sw.Append("});");//end foreach

            sw.Append("msgStore.clear().onsuccess = function(event) {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('clear all messages');");
                sw.Append("console.log(event);");
            }

            sw.Append("}; "); //end clear

            sw.Append("}; "); //end getall

            sw.Append("}; "); //end request onsuccess

            sw.Append("} else {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('failed to send message because IndexedDB not suppported in this browser');");
            }

            sw.Append("} ");



            sw.Append("}");  //end iterate
            sw.Append("};"); // end  priv
            sw.Append("} "); //end if priv
            sw.Append("} "); //end build function

            sw.Append("if(priv) {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('returning ready priv');");
            }

            sw.Append("return priv;");
            sw.Append("}");

            sw.Append("build();");
            sw.Append("return priv;");
            sw.Append("}; "); //end function

            sw.Append("if(!self.messageList) {");

            sw.Append("self.messageList = messageListBuilder(); ");
            sw.Append("} ");



            sw.Append("self.addEventListener('message', function(event){");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('SW Received Message ' + new Date().toString());");
                sw.Append("console.log(event);");
            }


            sw.Append("if(event.data.type === 'page-ready') {");
            sw.Append("if(self.messageList) {");
            sw.Append("self.messageList.iterate(sendMessage);");

            //sw.Append("sendMessage({type:'hello' });");
            sw.Append("} ");


            sw.Append("}"); //endif windowready

            sw.Append("}); ");

            #endregion


            #region pushmanager

            sw.Append("if ('PushManager' in self) {");


            await _configurePushApiMethods.AppendToInitScript(sw, context, urlHelper);

            //sw.AppendLine("self.importScripts('/pwa/js/push-notifications-controller.js');");

            sw.Append("self.addEventListener('push', function (event) {");


            sw.Append("var json = event.data.json();");

            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log(json);");
            }

            sw.Append("const precacheCacheName = workbox.core.cacheNames.runtime;");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('pre-cache name is ' + precacheCacheName);");
            }


            // --- content add begin

            sw.Append("if(json.messageType === 'newcontent') {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('content add');");
            }

            sw.Append("caches.open(precacheCacheName).then(function(cache) {");

            sw.Append("fetch(json.data).then(function (response) {");
            sw.Append("cache.put(json.data, response.clone()).then(function () {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('added item to cache');");
            }

            sw.Append("});");
            sw.Append("});");


            sw.Append("});"); //end cache open
            sw.Append("}");
            // --- content add end


            // --- content update begin

            sw.Append("if(json.messageType === 'contentupdate') {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('content update');");
            }

            sw.Append("caches.open(precacheCacheName).then(function(cache) {");


            //sw.Append("var key = workbox.precaching.getCacheKeyForURL(json.data);");
            //if (options.EnableServiceWorkerConsoleLog)
            //{
            //    sw.Append("console.log('key is ' + key);");
            //}

            sw.Append("cache.delete(json.data).then(function(response) {");

            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log(response);");
            }

            sw.Append("if(response === true) {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('deleted from cache');");
            }


            sw.Append("fetch(json.data).then(function (response) {");
            sw.Append("cache.put(json.data, response.clone()).then(function () {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('updated cache');");
            }

            sw.Append("let msg = { type:'cacheupdate', url: json.data, id: json.data }; ");

            sw.Append("if(self.messageList) {");
            sw.Append("self.messageList.addMessage(msg);");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('added new message ' + new Date().toString())");
            }


            sw.Append("} ");



            sw.Append("});");
            sw.Append("});");



            sw.Append("}");   //end if delete response === true

            sw.Append("});"); //end delete



            sw.Append("})"); //end cache open

            sw.Append("};"); //end if contentupdate

            /// --- content update end

            /// -- content delete

            sw.Append("if(json.messageType === 'contentdelete') {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('content delete');");
            }

            sw.Append("caches.open(precacheCacheName).then(function(cache) {");

            sw.Append("cache.delete(json.data).then(function(response) {");

            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('removed item from cache');");
            }

            sw.Append("});"); //end delete

            sw.Append("});"); //end cache open
            sw.Append("}");

            /// --- content delete end



            sw.Append("if(json.messageType === 'Visible') {");
            sw.Append("event.waitUntil(self.registration.showNotification(json.title, json));");
            sw.Append("} else {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('non visible message');");
            }


            sw.Append("return;"); //cancel notification
            sw.Append("}");

            sw.Append("});"); //end push event



            sw.Append("self.addEventListener('pushsubscriptionchange', function (event) {");

            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('push subscription change');");
            }

            sw.Append("const handlePushSubscriptionChangePromise = Promise.resolve();");

            sw.Append("if (event.oldSubscription) {");

            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('old subscription');");
            }

            sw.Append("handlePushSubscriptionChangePromise = handlePushSubscriptionChangePromise.then(function () {");
            sw.Append("return PushNotificationsController.discardPushSubscription(event.oldSubscription);");
            sw.Append("});");
            sw.Append("}");

            sw.Append("if (event.newSubscription) {");

            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('new subscription');");
            }

            sw.Append("handlePushSubscriptionChangePromise = handlePushSubscriptionChangePromise.then(function () {");
            sw.Append("return PushNotificationsController.storePushSubscription(event.newSubscription);");
            sw.Append("});");
            sw.Append("}");

            sw.Append("if (!event.newSubscription) {");

            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('not new subscription');");
            }

            sw.Append("handlePushSubscriptionChangePromise = handlePushSubscriptionChangePromise.then(function () {");
            sw.Append("return PushNotificationsController.retrievePublicKey().then(function (applicationServerPublicKey) {");
            sw.Append("return pushServiceWorkerRegistration.pushManager.subscribe({");
            sw.Append("userVisibleOnly: true,");
            sw.Append("applicationServerKey: applicationServerPublicKey");
            sw.Append("}).then(function (pushSubscription) {");
            sw.Append("return PushNotificationsController.storePushSubscription(pushSubscription);");
            sw.Append("});");
            sw.Append("});");
            sw.Append("});");
            sw.Append("}");


            sw.Append("event.waitUntil(handlePushSubscriptionChangePromise);");
            sw.Append("});");

            sw.Append("self.addEventListener('notificationclick', function (event) {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log(event);");
            }

            //sw.Append("event.notification.close();");
            sw.Append("});");

            sw.Append("} else {");
            if (options.EnableServiceWorkerConsoleLog)
            {
                sw.Append("console.log('PushManager NOT supported');");
            }

            sw.Append("} ");

            #endregion

            //return Task.CompletedTask;
        }
Exemple #2
0
        public async Task <string> BuildPwaInitScript(HttpContext context, IUrlHelper urlHelper)
        {
            var url = urlHelper.RouteUrl(_pwaRouteNameProvider.GetServiceWorkerRouteName());

            var script = new StringBuilder();

            await _configurePushApiMethods.AppendToInitScript(script, context, urlHelper);

            var canShowPush = true;

            if (_options.RequireCookieConsentBeforeRegisteringServiceWorker)
            {
                var consentFeature = context.Features.Get <ITrackingConsentFeature>();
                if (consentFeature != null && !consentFeature.CanTrack)
                {
                    canShowPush = false;
                }
            }

            if (canShowPush)
            {
                var assembly         = typeof(DefaultGeneratePwaInitScript).GetTypeInfo().Assembly;
                var userSettingsFile = baseResourcePath + "push-user-settings.min.js";
                using (var resourceStream = assembly.GetManifestResourceStream(userSettingsFile))
                {
                    using (StreamReader reader = new StreamReader(resourceStream))
                    {
                        string s = reader.ReadToEnd();

                        script.Append(s);
                    }
                }
            }



            if (_options.SetupInstallPrompt)
            {
                script.Append("let deferredPrompt;");
                //script.Append("let divPrompt = document.getElementById('divPwaInstallPrompt');");
                script.Append("let btnInstall = document.getElementById('btnPwaInstall');");
                //script.Append("let pwaHeading = document.getElementById('pwaInstallHeading');");
                script.Append("if(btnInstall) {");


                script.Append("window.addEventListener('beforeinstallprompt', (e) => {");
                // Prevent Chrome 67 and earlier from automatically showing the prompt
                script.Append("e.preventDefault();");
                // Stash the event so it can be triggered later.
                script.Append("deferredPrompt = e;");

                //update the UI notify the user
                //script.Append("divPrompt.classList.add('show');");
                //script.Append("divPrompt.style.display ='block';");
                //script.Append("pwaHeading.style.display = 'block';");
                script.Append("btnInstall.style.display = 'inline-block';");

                script.Append("});");


                script.Append("btnInstall.addEventListener('click', (e) => {");

                //script.Append("document.getElementById('divPwaInstallPrompt').classList.remove('show');");
                // script.Append("divPrompt.style.display ='none';");
                // Show the prompt
                script.Append("deferredPrompt.prompt();");
                // Wait for the user to respond to the prompt
                script.Append("deferredPrompt.userChoice");
                script.Append(".then((choiceResult) => {");
                script.Append("if (choiceResult.outcome === 'accepted') {");
                script.Append("console.log('User accepted the A2HS prompt');");
                script.Append("} else {");
                script.Append("console.log('User dismissed the A2HS prompt');");
                script.Append("}");
                script.Append("deferredPrompt = null;");
                script.Append("});");
                script.Append("});");


                script.Append("} ");
            }



            script.AppendLine("import {Workbox} from '" + _options.WorkBoxWindowModuleUrl + "';");


            script.Append("if ('serviceWorker' in navigator) {");
            //script.Append("window.addEventListener('load', () => {");

            var scope = _pwaRouteNameProvider.GetServiceWorkerScope();

            script.Append("const wb = new Workbox('" + url + "',{scope: '" + scope + "'});");

            //activated event
            script.Append("wb.addEventListener('activated', (event) => {");

            script.Append("if (!event.isUpdate) {");
            script.Append("console.log('Service worker activated for the first time');");
            script.Append("} else {");
            script.Append("console.log('Service worker activated');");
            script.Append("}");

            var items = new List <ServiceWorkerCacheItem>();

            foreach (var provider in _preCacheProviders)
            {
                var i = await provider.GetItems();

                items.AddRange(i);
            }

            script.Append("const urlsToCache = [");
            var comma = "";

            foreach (var item in items)
            {
                script.Append(comma);
                if (!string.IsNullOrEmpty(item.Revision))
                {
                    script.Append("{");
                    script.Append("\"url\": \"" + item.Url + "\",");
                    script.Append("\"revision\": \"" + item.Revision + "\"");

                    script.Append("}");
                }
                else
                {
                    script.Append("'" + item.Url + "'");
                }

                comma = ",";
            }


            script.Append("];");
            script.Append("wb.messageSW({");
            script.Append("type: 'CACHE_URLS',");
            script.Append("payload: {urlsToCache} ");
            script.Append("});");



            script.Append("});"); //end activated event



            script.Append("wb.addEventListener('waiting', (event) => {");
            script.Append("console.log('new service worker waiting');");
            script.Append("});");

            script.Append("wb.addEventListener('installed', (event) => {");
            script.Append("if (!event.isUpdate) {");
            // First-installed code goes here...
            script.Append("console.log('Service worker installed for the first time');");
            script.Append("} else {");
            script.Append("console.log('new service worker installed');");
            script.Append("}");
            script.Append("});");

            script.Append("wb.addEventListener('controlling', (event) => {");
            script.Append("console.log('new service worker controlling');");

            if (_options.ReloadPageOnServiceWorkerUpdate)
            {
                script.Append("var refreshing;");

                if (_options.EnableServiceWorkerConsoleLog)
                {
                    script.Append("console.log('Controller loaded');");
                }

                script.Append("if (refreshing) return;");
                script.Append("refreshing = true;");
                script.Append("if(!window.location.href.indexOf('account') > -1) {");


                if (_options.EnableServiceWorkerConsoleLog)
                {
                    script.Append("console.log('reloading page because service worker updated');");
                }
                //this causes login to fail
                script.Append("window.location.reload();");

                script.Append("}");
            }

            script.Append("});");

            script.Append("wb.addEventListener('redundant', (event) => {");
            script.Append("console.log('service worker redundant fired');");
            script.Append("});");

            script.Append("wb.addEventListener('externalinstalled', (event) => {");
            script.Append("console.log('service worker externalinstalled fired');");
            script.Append("});");

            script.Append("wb.addEventListener('externalwaiting', (event) => {");
            script.Append("console.log('service worker externalwaiting fired');");
            script.Append("});");

            script.Append("wb.addEventListener('externalactivated', (event) => {");
            script.Append("console.log('service worker externalactivated fired');");
            script.Append("});");

            //listen for messages from sw
            script.Append("wb.addEventListener('message', (event) => {");

            script.Append("console.log(`message received from serviceworker`);");
            script.Append("console.log(event);");

            //script.Append("if (event.data.type === 'CACHE_UPDATED') {");
            //script.Append("const {updatedURL} = event.data.payload;");
            //script.Append("console.log(`A newer version of ${updatedURL} is available!`);");
            //script.Append("} else {");
            //script.Append("console.log(`message received from serviceworker`);");
            //script.Append("console.log(event);");
            //script.Append("}");


            script.Append("}); ");// end message listener


            script.Append("if ('BroadcastChannel' in window) {");

            script.Append("const channel = new BroadcastChannel('app-channel');");
            script.Append("channel.onmessage = function(e) {");
            script.Append("console.log('received message on app channel');");
            script.Append("console.log(e);");

            script.Append("if(e.data.type === 'cacheupdate' && e.data.url === window.location.href) {");
            script.Append("console.log('cache update for current url so reloading');");
            script.Append("window.location.reload();");
            script.Append("}");
            script.Append("};");

            script.Append("} else {");
            script.Append("console.log('Broadcast channel not supported');");
            script.Append("} ");


            // Register the service worker after event listeners have been added.
            script.Append("wb.register();");


            // script.Append("});"); //end load event

            script.Append("if ('MessageChannel' in window) {");

            script.Append("navigator.serviceWorker.ready.then(function (serviceWorkerRegistration) {");
            script.Append("console.log('serviceworker ready');");

            script.Append("setTimeout(function() {");

            script.Append("if(navigator.serviceWorker.controller) {");
            script.Append("const messageChannel = new MessageChannel();");
            script.Append("navigator.serviceWorker.controller.postMessage(");
            script.Append("{type:'page-ready'}");
            script.Append(", [messageChannel.port2]);");
            script.Append("}");

            script.Append("},3000);");


            script.Append("});"); //end serviceworker ready

            script.Append("} else {");
            script.Append("console.log('MessageChannel not supported');");
            script.Append("} "); //end if MessageChannel



            script.Append("}"); //end serviceworker in navigator


            return(script.ToString());
            //return Task.FromResult(script.ToString());
        }