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
208 lines (186 loc) • 6.62 kB
JavaScript
/*global chrome*/
/**
* Long lived background script running in the browser, works in tandem with the
* client-script to coordinate messaging between EmberDebug, EmberInspector and the
* ClientApp. The background.js script serves as a proxy between the EmberInspector
* and the content-script.
*
* It is also responsible for showing the Ember icon and tooltip in the url bar.
*
* See:
* https://developer.chrome.com/extensions/background_pages
* https://developer.chrome.com/extensions/messaging
*/
(function() {
"use strict";
var activeTabs = {},
activeTabId,
contextMenuAdded = false,
emberInspectorChromePorts = {};
/**
* Creates the tooltip string to show the version of libraries used in the ClientApp
* @param {Array} versions - array of library objects
* @return {String} - string of library names and versions
*/
function generateVersionsTooltip(versions) {
return versions.map(function(lib) {
return lib.name + " " + lib.version;
}).join("\n");
}
/**
* Creates the title for the action for the current ClientApp
* @param {Number} tabId - the current tab
*/
function setActionTitle(tabId) {
void chrome.action.setTitle({
tabId: tabId,
title: generateVersionsTooltip(activeTabs[tabId])
});
}
/**
* Update the tab's action: https://developer.chrome.com/extensions/pageAction
* If the user has choosen to display it, the icon is shown and the title
* is updated to display the ClientApp's information in the tooltip.
* @param {Number} tabId - the current tab
*/
function updateTabAction(tabId) {
chrome.storage.sync.get("options", async function(data) {
void chrome.action.enable(tabId);
void chrome.action.setIcon({
tabId,
path: {
19: 'panes-3-16-0/assets/images/icon19.png',
38: 'panes-3-16-0/assets/images/icon38.png',
}
});
setActionTitle(tabId);
});
}
/**
* Remove the curent tab's Ember icon.
* Typically used to clearout the icon after reload.
* @param {Number} tabId - the current tab
*/
function hideAction(tabId) {
if (!activeTabs[tabId]) {
return;
}
void chrome.action.disable(tabId);
void chrome.action.setIcon({
tabId,
path: {
19: 'panes-3-16-0/assets/images/icon19_grey.png',
38: 'panes-3-16-0/assets/images/icon38_grey.png',
}
});
}
function genericOnClick(info) {
if (info.menuItemId !== 'inspect-ember-component') return;
void chrome.tabs.sendMessage(activeTabId, {
from: 'devtools',
type: 'view:contextMenu'
});
}
chrome.contextMenus.onClicked.addListener(genericOnClick);
/**
* Update the tab's contextMenu: https://developer.chrome.com/extensions/contextMenus
* Add a menu item called "Inspect Ember Component" that shows info
* about the component in the inspector.
* @param {Boolean} force don't use the activeTabs array to check for an existing context menu
*/
function updateContextMenu(force) {
// The Chromium that Electron runs does not have a chrome.contextMenus,
// so make sure this doesn't throw an error in Electron
if (!chrome.contextMenus) {
return;
}
// Only add context menu item when an Ember app has been detected
var isEmberApp = !!activeTabs[activeTabId] || force;
if (!isEmberApp && contextMenuAdded) {
chrome.contextMenus.remove('inspect-ember-component');
contextMenuAdded = false;
}
if (isEmberApp && !contextMenuAdded) {
chrome.contextMenus.create({
id: 'inspect-ember-component',
title: 'Inspect Ember Component',
contexts: ['all'],
});
contextMenuAdded = true;
}
}
/**
* Listen for a connection request from the EmberInspector.
* When the EmberInspector connects to the extension a messageListener
* is added for the specific EmberInspector instance, and saved into
* an array, keyed by appId.
*
* @param {Port} emberInspectorChromePort
*/
chrome.runtime.onConnect.addListener(function(emberInspectorChromePort) {
var appId;
/**
* Listen for messages from the EmberInspector.
* The first message is used to save the port, all others are forwarded
* to the content-script.
* @param {Message} message
*/
emberInspectorChromePort.onMessage.addListener(function(message) {
// if the message contains the appId, this is the first
// message and the appId is used to map the port for this app.
if (message.appId) {
appId = message.appId;
emberInspectorChromePorts[appId] = emberInspectorChromePort;
emberInspectorChromePort.onDisconnect.addListener(function() {
delete emberInspectorChromePorts[appId];
});
} else if (message.from === 'devtools') {
// all other messages from EmberInspector are forwarded to the content-script
// https://developer.chrome.com/extensions/tabs#method-sendMessage
chrome.tabs.sendMessage(message.tabId || appId, message, { frameId: message.frameId });
}
});
});
/**
* Listen for messages from the content-script.
* A few events trigger specfic behavior, all others are forwarded to EmberInspector.
* @param {Object} request
* @param {MessageSender} sender
*/
chrome.runtime.onMessage.addListener(function(request, sender) {
// only listen to messages from the content-script
if (!sender.tab) {
// noop
} else if (request && request.type === 'emberVersion') {
// set the version info and update title
activeTabs[sender.tab.id] = request.versions;
updateTabAction(sender.tab.id);
updateContextMenu();
} else if (request && request.type === 'resetEmberIcon') {
// hide the Ember icon
hideAction(sender.tab.id);
} else if (request && request.type === 'inspectorLoaded') {
updateContextMenu(true);
} else {
// forward the message to EmberInspector
var emberInspectorChromePort = emberInspectorChromePorts[sender.tab.id];
if (emberInspectorChromePort) { emberInspectorChromePort.postMessage(request); }
}
});
/**
* Keep track of which browser tab is active and update the context menu.
*/
chrome.tabs.onActivated.addListener(({ tabId }) => {
activeTabId = tabId;
if (activeTabs[tabId]) {
updateTabAction(tabId);
}
updateContextMenu();
});
/**
* Only keep track of active tabs
*/
chrome.tabs.onRemoved.addListener(({ tabId }) => {
delete activeTabs[tabId];
});
}());