UNPKG

electron-devtools-vendor

Version:

<div align="center"> <h2>electron-devtools-vendor</h2> <img alt="MIT" src="https://img.shields.io/github/license/BlackHole1/electron-devtools-vendor?color=9cf&style=flat-square"> <img alt="GitHub repo size" src="https://img.shields.io/github/r

119 lines (97 loc) 4.38 kB
var contentScript = new (function() { // singleton // as per chrome, frameURL is the ORIGINAL frame url without eventual hash string this.frameURL = window.location.origin + window.location.pathname + window.location.search; this.isTopFrame = (window.parent == window); // Setup an Inspected page <-> Content script peer to peer MessageChannel connection. // Since we don't know which of the two will start first, they both do the same thing: // on start we send the started message, if the other didn't started yet, then the message will // never be received by it, but in that case we'll receive its started message, // we'll then send the connect message since we're now sure that the other is ready to receive // our port (it can only be sent once since the object ownership is transferred (neutered)), // and we'll resend also the started message that will be received too for sure; // the other end will thus receive the connect message, to which it reacts // by listening to the port, and the started message, to which reacts // by sending its connect message and its started message. // Finally, we'll receive the connect message, to which we react by listening, // and the started message again, that we'll just ignore. // In the meantime, they both can send messages to the out ports, even if the other didn't // received it yet, since the MessageChannel port start() method emits all the messages // received until that moment. this.isConnectedWithPage = false; this.channel = undefined; this.pagePortOut = undefined; this.pagePortIn = undefined; this.initialize = function() { this.channel = new MessageChannel(); this.pagePortOut = this.channel.port1; this.waitForPage(); this.notifyStartToPage(); this.listenToBackground(); if (this.isTopFrame) this.ifTopFrame(); }; this.waitForPage = function() { window.addEventListener('message', (function(event) { // Only accept messages from same frame if (event.source != window) return; var message = event.data; // Only accept our messages if (typeof message != 'object' || message === null || message.target != 'page') return; if (message.name == 'started' && !this.isConnectedWithPage) { // now we are sure the other is ready to receive our port this.connectToPage(); // this is needed if the content script started before the page // (in that case the inspected page never received the initial 'active' message) this.notifyStartToPage(); } else if (message.name == 'connect' && !this.pagePortIn) { this.pagePortIn = event.ports[0]; this.listenToPage(); } }).bind(this)); }; this.notifyStartToPage = function() { window.postMessage({ target: 'extension', timestamp: new Date().getTime(), name: 'started' }, '*'); }; // this must be called only once since the port ownership is transferred (neutered)! this.connectToPage = function() { window.postMessage({ target: 'extension', timestamp: new Date().getTime(), name: 'connect' }, '*', [this.channel.port2]); this.isConnectedWithPage = true; }; // Listens to inspected page frame messages and redirects them to the background, // building up the first step towards the communication between the backbone agent and the panel. this.listenToPage = function() { this.pagePortIn.addEventListener('message', (function(event) { var message = event.data; message.frameURL = this.frameURL; chrome.runtime.sendMessage(message); }).bind(this)); this.pagePortIn.start(); }; // Receives messages from the background and redirects them to the inspected page. this.listenToBackground = function() { chrome.runtime.onMessage.addListener((function(message) { // Only accept messages for our frame if (message.frameURL != this.frameURL) return; this.pagePortOut.postMessage(message); }).bind(this)); }; // Code to be executed only if this is the top frame content script! this.ifTopFrame = function() { // Sends a message to the background when the DOM of the inspected page is ready // (typically used by the panel to check if the backbone agent is on the page). window.addEventListener('DOMContentLoaded', function() { chrome.runtime.sendMessage({ target: 'page', name: 'ready' }); }, false); }; this.initialize(); })();