UNPKG

broadcast-message

Version:

基于postMessage+BroadcastChannel+localStorage+互信域名的前端页面数据通信解决方案

37 lines (35 loc) 15 kB
var l=Object.defineProperty;var f=(_,e,s)=>e in _?l(_,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):_[e]=s;var o=(_,e,s)=>(f(_,typeof e!="symbol"?e+"":e,s),s);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))t(r);new MutationObserver(r=>{for(const a of r)if(a.type==="childList")for(const n of a.addedNodes)n.tagName==="LINK"&&n.rel==="modulepreload"&&t(n)}).observe(document,{childList:!0,subtree:!0});function s(r){const a={};return r.integrity&&(a.integrity=r.integrity),r.referrerpolicy&&(a.referrerPolicy=r.referrerpolicy),r.crossorigin==="use-credentials"?a.credentials="include":r.crossorigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function t(r){if(r.ep)return;r.ep=!0;const a=s(r);fetch(r.href,a)}})();/*! * @name url.js * @description 用于对url进行解析的相关方法 * @version 0.0.1 * @author Blaze * @date 27/03/2019 15:52 * @github https://github.com/xxxily */function c(_){var e=document.createElement("a");return e.href=_||window.location.href,{source:_,protocol:e.protocol.replace(":",""),host:e.hostname,port:e.port,origin:e.origin,search:e.search,query:e.search,file:(e.pathname.match(/\/([^/?#]+)$/i)||["",""])[1],hash:e.hash.replace("#",""),path:e.pathname.replace(/^([^/])/,"/$1"),relative:(e.href.match(/tps?:\/\/[^/]+(.+)/)||["",""])[1],params:function(){const s={},t=[];for(var r=e.search.replace(/^\?/,"").split("&"),a=0;a<r.length;a++){var n=r[a];n!==""&&n.indexOf("=")&&t.push(n)}for(var i=0;i<t.length;i++){var u=t[i],d=u.indexOf("="),g=u.substring(0,d),h=u.substring(d+1);g?s[g]=h:s[h]=null}return s}()}}function w(_){var e=[];if(Object.prototype.toString.call(_)!=="[object Object]")return"";for(var s in _)if(Object.hasOwnProperty.call(_,s)){var t=_[s],r=Object.prototype.toString.call(t);if(t===""||r==="[object Undefined]")continue;t===null?e.push(s):r==="[object Array]"?e.push(s+"="+t.join(",")):(t=(JSON.stringify(t)||""+t).replace(/(^"|"$)/g,""),e.push(s+"="+t))}return e.join("&")}function m(_){var e=w(_.params)||"";e&&(e="?"+e);var s=_.hash?"#"+_.hash:"";return _.origin+_.path+e+s}/*! * @name BroadcastMessage.js * @description 基于postMessage+BroadcastChannel+localStorage+互信域名的前端页面数据通信解决方案 * @version 0.0.1 * @author xxxily * @date 2022/11/07 09:26 * @github https://github.com/xxxily */class I{constructor(e={}){o(this,"debug");o(this,"targetOrigin");o(this,"transportType");o(this,"inTrustedDomainPages");o(this,"allowLocalBroadcast");o(this,"channelId");o(this,"instanceId");o(this,"emitOriginalMessage");o(this,"readyTime");o(this,"messageWindow");o(this,"trustedDomainPages");o(this,"__hasRegisterPostMessageListener__");o(this,"__BroadcastChannelInstance__");o(this,"__hasRegisterStorageListener__");o(this,"__readyHandler__");o(this,"_readyStartTime_");o(this,"_isReady_");o(this,"__messageListener__");o(this,"__internalMessageListener__");o(this,"__hasInternalMessageListener__");o(this,"__hasMessageListener__");o(this,"_message_cache_");this.targetOrigin=e.targetOrigin||location.origin,this.transportType=e.transportType||"BroadcastChannel",this.inTrustedDomainPages=e.inTrustedDomainPages||!1,this.trustedDomainPages=e.trustedDomainPages||"",this.allowLocalBroadcast=e.allowLocalBroadcast||!1,this.channelId=String(e.channelId||"*"),this.instanceId=this.channelId+"_"+(window.performance?performance.now():Date.now()),this.debug=e.debug||!1,this.emitOriginalMessage=e.emitOriginalMessage||!1,this.messageWindow=window,this.readyTime=0,this._isReady_=!1,this.__messageListener__=[],this.__internalMessageListener__=[],this.init()}init(){if(this.trustedDomainPages){const e=c(this.trustedDomainPages);e.params.channelId=this.channelId,e.params.instanceId=this.instanceId,this.trustedDomainPages=m(e)}this.__registerMessageWindow__(),this.inTrustedDomainPages&&window.top&&window!==window.top.window&&(this.__registerPostMessageListener__(),this.__registerStorageMessageListener__(),this.__registerBroadcastChannelListener__(),this.__sendMessageToParentWindow__("initReady"))}getTrustedDomain(){return this.trustedDomainPages?c(this.trustedDomainPages).origin:location.origin}__sendMessageToParentWindow__(e){if(window.parent===window||!e)return;const s=window.__broadcastMessageChannelId__||this.channelId,t=window.__broadcastMessageInstanceId__||this.instanceId;window.parent.postMessage({data:e,channelId:s,instanceId:t,type:"Internal-BroadcastMessage"},"*")}__registerMessageWindow__(){if(this.messageWindow!==window)return;const e=document.createElement("iframe");if(e.style.display="none",e.style.visibility="hidden",e.src=this.trustedDomainPages,e.className="broadcast-message-iframe",document.body.appendChild(e),this.messageWindow=e.contentWindow,!this.inTrustedDomainPages&&!this.trustedDomainPages&&this.messageWindow&&this.messageWindow.document){const s=this.messageWindow.document;if(!s.body){const t=s.createElement("body");t.innerHTML="<h1>Broadcast-Message-page</h1>",s.documentElement.appendChild(t)}s.open(),s.write(` <script> function ${this.__registerPostMessageListener__}; function ${this.__registerStorageMessageListener__}; function ${this.__registerBroadcastChannelListener__}; function ${this.__sendMessageToParentWindow__}; function init () { if (window.__hasInit__) { return false; } window.__broadcastMessageChannelId__ = "${this.channelId}"; window.__broadcastMessageInstanceId__ = "${this.instanceId}"; __registerPostMessageListener__(); __registerStorageMessageListener__(); __registerBroadcastChannelListener__(); __sendMessageToParentWindow__('initReady'); window.__hasInit__ = true ; } document.addEventListener("DOMContentLoaded", init); window.addEventListener("load", init) setTimeout(init, 100) <\/script> `),s.close()}}__registerPostMessageListener__(){const e=this;if(e.__hasRegisterPostMessageListener__||window.top===window)return!1;if(window.__windowId__=String((Date.now()-Math.random()*1e5).toFixed(2)),!window.__broadcastMessageChannelId__)try{const a=c(location.href);if(a.params.channelId&&a.params.instanceId)window.__broadcastMessageChannelId__=a.params.channelId,window.__broadcastMessageInstanceId__=a.params.instanceId;else throw new Error("URL\u7F3A\u5931\u76F8\u5173\u53C2\u6570")}catch(a){console.error(`[registerPostMessageListener][${location.origin}] \u83B7\u53D6broadcastMessageChannelId\u5931\u8D25`,a)}function s(){let a=document.querySelector("#message-transport-iframe");return a||(a=document.createElement("iframe"),a.id="message-transport-iframe",a.style.display="none",a.style.visibility="hidden",document.body.appendChild(a),a)}function t(a){const n=a.data;n.windowId=window.__windowId__,n.debug&&console.log(`[transportMessage][iframe][${location.origin}]`);const i=s().contentWindow;if(!i)throw new Error("[transportMessage][iframe]\u7528\u4E8E\u6D88\u606F\u4E2D\u8F6C\u7684iframe\u4E0D\u5B58\u5728\uFF0C\u68C0\u6D4B\u662F\u5426\u610F\u5916\u5220\u9664\u4E86");if(i.BroadcastChannel&&i.BroadcastChannel.prototype.postMessage&&n.transportType!=="localStorage"){const d=i.__BroadcastChannelInstance__||new i.BroadcastChannel("__BroadcastChannelMessage__");i.__BroadcastChannelInstance__=i.__BroadcastChannelInstance__||d,d.postMessage(n)}else i.localStorage.setItem("__BroadcastMessage__",JSON.stringify(n))}s();function r(a){const n=a.data;if(!n)return!1;if(n.data==="readyTest"){window.__broadcastMessageReadyInfo__=n;const i=e.__sendMessageToParentWindow__||window.__sendMessageToParentWindow__;i instanceof Function&&i("ready")}}window.addEventListener("message",a=>{const n=a.data;if(!n||!n.type)return!1;n.type==="BroadcastMessage"?t(a):n.type==="Internal-BroadcastMessage"&&r(a)},!0),this.__hasRegisterPostMessageListener__=!0}__registerBroadcastChannelListener__(){if(!window.BroadcastChannel||!BroadcastChannel.prototype.postMessage)return console.error(`[BroadcastChannel][${location.origin}]`,"\u4E0D\u652F\u6301BroadcastChannel"),!1;if(this.__BroadcastChannelInstance__)return!0;const e=new BroadcastChannel("__BroadcastChannelMessage__");e.addEventListener("message",s=>{const t=s.data;if(!t||!t.windowId||!t.data)return!1;const r=window.__broadcastMessageChannelId__;if(!t.channelId||r&&t.channelId!==r)return t.debug&&console.info("[transportMessage] channelId\u4E0D\u5B58\u5728\u6216\u4E0D\u5339\u914D\uFF0C\u7981\u6B62\u6570\u636E\u5411\u4E0A\u4F20\u9012",r,t),!1;if(!t.allowLocalBroadcast&&window.__windowId__&&window.__windowId__===t.windowId)return t.debug&&console.info("[BroadcastChannel-event] \u6D88\u606F\u6E90\u63A5\u6536\u7AEF\u548C\u6D88\u606F\u6E90\u7684\u6765\u6E90\u7AEF\u4E00\u81F4\uFF0C\u7981\u6B62\u6570\u636E\u5411\u4E0A\u4F20\u9012"),!1;(Array.isArray(t.targetOrigin)?t.targetOrigin:[t.targetOrigin]).forEach(n=>{const i=window.__broadcastMessageReadyInfo__||null;if(n!=="*"&&(!i||!i.referrer.startsWith(n)))return t.instanceId!==i.instanceId&&t.debug&&console.warn(`[BroadcastChannel-event] \u6D88\u606F\u7684targetOrigin\u548C\u5F53\u524D\u7236\u9875\u9762\u7684\u5730\u5740\u4E0D\u5339\u914D\uFF0C\u53D6\u6D88\u6570\u636E\u5411\u4E0A\u4F20\u9012\uFF0C[targetOrigin]${n} [parent page]${i.referrer}`),!1;window.parent.postMessage(t,n)})}),this.__BroadcastChannelInstance__=e}__registerStorageMessageListener__(){if(this.__hasRegisterStorageListener__)return!1;window.addEventListener("storage",e=>{let s=e.newValue;if(!s||e.key!=="__BroadcastMessage__")return!1;try{s=JSON.parse(s)}catch(a){return!1}if(!s||!s.windowId||!s.data)return!1;const t=window.__broadcastMessageChannelId__;if(!s.channelId||t&&s.channelId!==t)return s.debug&&console.error("[transportMessage] channelId\u4E0D\u5B58\u5728\u6216\u4E0D\u5339\u914D\uFF0C\u7981\u6B62\u6570\u636E\u5411\u4E0A\u4F20\u9012",t,s),!1;if(s.debug&&console.log(`[storage-event][iframe][${location.origin}]`,e),!s.allowLocalBroadcast&&window.__windowId__&&window.__windowId__===s.windowId)return s.debug&&console.info("[storage-event] \u6D88\u606F\u6E90\u63A5\u6536\u7AEF\u548C\u6D88\u606F\u6E90\u7684\u6765\u6E90\u7AEF\u4E00\u81F4\uFF0C\u7981\u6B62\u6570\u636E\u5411\u4E0A\u4F20\u9012"),!1;(Array.isArray(s.targetOrigin)?s.targetOrigin:[s.targetOrigin]).forEach(a=>{const n=window.__broadcastMessageReadyInfo__||{referrer:""};if(a!=="*"&&!n.referrer.startsWith(a))return s.instanceId!==n.instanceId&&s.debug&&console.warn(`[storage-event] \u6D88\u606F\u7684targetOrigin\u548C\u5F53\u524D\u7236\u9875\u9762\u7684\u5730\u5740\u4E0D\u5339\u914D\uFF0C\u53D6\u6D88\u6570\u636E\u5411\u4E0A\u4F20\u9012\uFF0C[targetOrigin]${a} [parent page]${n.referrer}`),!1;window.parent.postMessage(s,a)})}),this.__hasRegisterStorageListener__=!0}postMessage(e,s){if(!this._isReady_&&s!=="Internal-BroadcastMessage")return this._message_cache_||this.ready(()=>{Array.isArray(this._message_cache_)&&(this._message_cache_.forEach(a=>{this.postMessage(a)}),delete this._message_cache_)}),this._message_cache_=this._message_cache_||[],this._message_cache_.push(e),!0;const t={data:e,type:s||"BroadcastMessage",origin:location.origin||window.top&&window.top.location.origin,targetOrigin:this.targetOrigin,referrer:location.href||window.top&&window.top.location.href,timeStamp:window.performance?performance.now():Date.now(),transportType:this.transportType,allowLocalBroadcast:this.allowLocalBroadcast,channelId:this.channelId,instanceId:this.instanceId,debug:this.debug};if(!this.messageWindow||!this.messageWindow.postMessage)return this.debug&&console.error("[messageWindow error] \u65E0\u6CD5\u53D1\u9001message",t,this.messageWindow),!1;const r=this.getTrustedDomain();this.messageWindow.postMessage(t,r)}onMessage(e){if(this.__messageListener__=this.__messageListener__||[],e instanceof Function&&!this.__messageListener__.includes(e)&&this.__messageListener__.push(e),this.__hasMessageListener__)return!1;this.__hasMessageListener__=!0,window.addEventListener("message",s=>{const t=s.data;if(!(t&&t.type==="BroadcastMessage"&&t.data&&t.channelId&&t.referrer))return!1;if(this.channelId!=="*"&&t.channelId!==this.channelId)return t.origin!==location.origin&&t.debug&&console.error("[messageListener] \u5B58\u5728\u6570\u636E\u5B89\u5168\u9690\u60A3\uFF0C\u8BF7\u5B8C\u5584\u811A\u672C\u903B\u8F91",this.channelId,s),!1;const a={};try{for(const n in s){let i=s[n];n==="data"&&!this.emitOriginalMessage?i=t.data:n==="type"&&(i="BroadcastMessage"),Object.defineProperty(a,n,{enumerable:n==="data",writable:!1,configurable:!0,value:i})}}catch(n){}this.__messageListener__.forEach(n=>{n instanceof Function&&n(a)})},!0)}offMessage(e){this.__messageListener__=this.__messageListener__||[];const s=[];this.__messageListener__.forEach(t=>{t!==e&&s.push(t)}),this.__messageListener__=s}postMessageToInternal(e){this.postMessage(e,"Internal-BroadcastMessage")}onInternalMessage(e){if(this.__internalMessageListener__=this.__internalMessageListener__||[],e instanceof Function&&!this.__internalMessageListener__.includes(e)&&this.__internalMessageListener__.push(e),this.__hasInternalMessageListener__)return!1;this.__hasInternalMessageListener__=!0,window.addEventListener("message",s=>{const t=s.data;return t&&t.type==="Internal-BroadcastMessage"&&t.channelId===this.channelId&&t.instanceId===this.instanceId?(this.__internalMessageListener__.forEach(a=>{a instanceof Function&&a(s)}),!0):!1},!0)}offInternalMessage(e){this.__internalMessageListener__=this.__internalMessageListener__||[];const s=[];this.__internalMessageListener__.forEach(t=>{t!==e&&s.push(t)}),this.__internalMessageListener__=s}addEventListener(e,s){if(e!=="message")return!1;this.onMessage(s)}removeEventListener(e,s){if(e!=="message")return!1;this.offMessage(s)}ready(e){if(this._isReady_)return e instanceof Function&&e(!0),!0;if(!this.__readyHandler__){this._readyStartTime_=Date.now(),this.__readyHandler__=[];const s=t=>{const r=t.data;r.data==="initReady"?this.postMessageToInternal("readyTest"):r.data==="ready"&&(this._isReady_=!0,this._readyStartTime_&&(this.readyTime=Date.now()-this._readyStartTime_),delete this._readyStartTime_,this.debug&&console.log(`[BroadcastMessage][ready] \u8017\u65F6\uFF1A${this.readyTime}`),Array.isArray(this.__readyHandler__)&&this.__readyHandler__.forEach(a=>{a instanceof Function&&a(!0)}),delete this.__readyHandler__,this.offInternalMessage(s))};this.onInternalMessage(s)}if(e instanceof Function)this.__readyHandler__.push(e);else return new Promise(s=>{Array.isArray(this.__readyHandler__)&&this.__readyHandler__.push(s)})}close(){this.__BroadcastChannelInstance__&&this.__BroadcastChannelInstance__.close&&this.__BroadcastChannelInstance__.close(),this.messageWindow&&this.messageWindow instanceof HTMLElement&&document.body.removeChild(this.messageWindow),this.__messageListener__=[],this.__readyHandler__=[]}}export{I as B};