diff --git a/webcommon/extbrowser.chrome/plugins/chrome/css/infobar.css b/webcommon/extbrowser.chrome/plugins/chrome/css/infobar.css deleted file mode 100644 index 8f4b90632d90..000000000000 --- a/webcommon/extbrowser.chrome/plugins/chrome/css/infobar.css +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -body { - font-family: Tahoma, Helvetica; - font-size: 12px; -} -a { - text-decoration: none; -} - -button, .button { - cursor: pointer; - font-weight: bold; - position: relative; - margin-right: 4px; - background-color: orange; - border: 1px solid orange; - border-radius: 3px; - color: white; - padding: 3px 4px; - box-shadow: 1px 1px 5px #1D1D1D; -} -button:hover, .button:hover { - background-color: darkorange; -} -button.disabled, button[disabled=disabled], .button.disabled { - cursor: not-allowed; - border: 1px solid grey; - background-color: grey; -} -button.disabled:hover, button[disabled=disabled]:hover, .button.disabled:hover { - background-color: grey; -} - -div.button { - padding: 1px 0px 0px 0px; -} -#selectionModeMenu { - color: white; - padding-top: 2px; - padding-right: 4px; -} - -#preview * { - float: left; -} diff --git a/webcommon/extbrowser.chrome/plugins/chrome/html/infobar.html b/webcommon/extbrowser.chrome/plugins/chrome/html/infobar.html deleted file mode 100644 index c44f4dcc3bd9..000000000000 --- a/webcommon/extbrowser.chrome/plugins/chrome/html/infobar.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - -
-
-
Loading presets...
- Auto - … -
- - Select Mode -
-
-
- - - diff --git a/webcommon/extbrowser.chrome/plugins/chrome/html/main.html b/webcommon/extbrowser.chrome/plugins/chrome/html/main.html deleted file mode 100644 index 26b90335c873..000000000000 --- a/webcommon/extbrowser.chrome/plugins/chrome/html/main.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - Background page of NetBeans Connector - - - - - - \ No newline at end of file diff --git a/webcommon/extbrowser.chrome/plugins/chrome/html/options.html b/webcommon/extbrowser.chrome/plugins/chrome/html/options.html index b704dc73e949..5ecc76654e36 100644 --- a/webcommon/extbrowser.chrome/plugins/chrome/html/options.html +++ b/webcommon/extbrowser.chrome/plugins/chrome/html/options.html @@ -27,6 +27,7 @@ + diff --git a/webcommon/extbrowser.chrome/plugins/chrome/html/popup.html b/webcommon/extbrowser.chrome/plugins/chrome/html/popup.html index e91b656fa349..d04e20a33cfe 100644 --- a/webcommon/extbrowser.chrome/plugins/chrome/html/popup.html +++ b/webcommon/extbrowser.chrome/plugins/chrome/html/popup.html @@ -27,6 +27,7 @@ + diff --git a/webcommon/extbrowser.chrome/plugins/chrome/js/background.js b/webcommon/extbrowser.chrome/plugins/chrome/js/background.js new file mode 100644 index 000000000000..137a1d4b8735 --- /dev/null +++ b/webcommon/extbrowser.chrome/plugins/chrome/js/background.js @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +importScripts('../i18n/i18n.js', 'preset.js', 'common.js', 'chrome.js'); + +chrome.runtime.onMessage.addListener((message, sender, respond) => { + if (sender.id !== chrome.runtime.id || !message?.action) { + return; + } + handleAction(message).then(respond, error => { + console.warn('NetBeans action failed:', error); + respond(false); + }); + return true; +}); + +async function handleAction({action, tabId, value, ident, resource, content}) { + const managed = NetBeans.socketReady && NetBeans.tabStatus(tabId) === NetBeans.STATUS_MANAGED; + switch (action) { + case 'popup': + if (tabId === NetBeans.debuggedTab) { + await new Promise(resolve => NetBeans.detectViewPort(resolve)); + } + return { + presets: NetBeans_Presets.getPresets(), + debuggedTab: NetBeans.debuggedTab, + selectionMode: NetBeans.getSelectionMode(), + ideVersion: NetBeans.ideVersion, + viewport: NetBeans_ViewPort + }; + case 'resize': + if (managed) { + NetBeans.resizePage(value); + } + return managed; + case 'inspect': + if (managed) { + const tab = await chrome.tabs.get(tabId); + return NetBeans.sendMessage({message: 'inspect', tabId, url: tab.url}); + } + return false; + case 'selection': + if (managed && tabId === NetBeans.debuggedTab && typeof value === 'boolean') { + NetBeans.setSelectionMode(value); + return true; + } + return false; + case 'presets': + return NetBeans_Presets.getPresets(true); + case 'savePresets': + if (NetBeans.socketReady && Array.isArray(value)) { + NetBeans_Presets.setPresets(value); + return true; + } + return false; + case 'resetWarnings': + NetBeans_Warnings.reset(); + return true; + case 'setWarning': + NetBeans_Warnings.enable(ident, value); + return true; + case 'getWriteBack': + return new Promise(resolve => NetBeans_DevTools.areChangesPropagated(resolve)); + case 'setWriteBack': + NetBeans_DevTools.setChangesPropagated(value === true); + return true; + case 'resourceCommitted': + if (managed && typeof resource?.url === 'string' && typeof content === 'string') { + const enabled = await new Promise(resolve => NetBeans_DevTools.areChangesPropagated(resolve)); + if (enabled && NetBeans.socketReady + && NetBeans.tabStatus(tabId) === NetBeans.STATUS_MANAGED) { + NetBeans.sendResourceChangedInCDT(resource, content); + return true; + } + } + return false; + default: + return false; + } +} + +chrome.alarms.onAlarm.addListener(alarm => { + if (alarm.name === 'netbeans-reconnect') { + NetBeans.connectIfNeeded(); + } +}); +chrome.runtime.onInstalled.addListener(() => { + chrome.alarms.create('netbeans-reconnect', {periodInMinutes: 1}); +}); +chrome.runtime.onStartup.addListener(() => NetBeans.connectIfNeeded()); +NetBeans.connectIfNeeded(); diff --git a/webcommon/extbrowser.chrome/plugins/chrome/js/chrome.js b/webcommon/extbrowser.chrome/plugins/chrome/js/chrome.js index 9d23f37c2cc8..4cf54f3f6c9f 100644 --- a/webcommon/extbrowser.chrome/plugins/chrome/js/chrome.js +++ b/webcommon/extbrowser.chrome/plugins/chrome/js/chrome.js @@ -20,13 +20,6 @@ // Initialization/cleanup NetBeans.cleanup(); -// Notify IDE that the extension has been installed/updated -chrome.runtime.onInstalled.addListener(function() { - var manifest = chrome.runtime.getManifest(); - var version = manifest.version; - NetBeans.sendReadyMessage(version); -}); - // Register reload-callback NetBeans.browserReloadCallback = function(tabId, newUrl) { if (newUrl !== undefined) { @@ -48,28 +41,33 @@ NetBeans.browserCloseCallback = function(tabId) { NetBeans.debuggedTab = null; NetBeans.windowWithDebuggedTab = null; +NetBeans.attachments = new Map(); +NetBeans.disconnectDebugger = function() { + for (const tabId of NetBeans.attachments.keys()) { + NetBeans.browserDetachDebugger(tabId); + } +}; NetBeans.browserAttachDebugger = function(tabId) { - if (NetBeans.DEBUG) { - console.log('debugger attach for tab ' + tabId); + if (NetBeans.attachments.has(tabId)) { + return; } - chrome.debugger.attach({tabId : tabId}, "1.0", function(){ - var err = chrome.runtime.lastError; - if (err) { - if (err.message) { - console.log('NetBeans cannot debug this tab because: ' + err.message); - } - } else { - if (NetBeans.debuggedTab !== null && NetBeans.debuggedTab !== tabId) { - NetBeans.hidePageIcon(NetBeans.debuggedTab); - } - NetBeans.debuggedTab = tabId; - chrome.tabs.get(tabId, function(tab) { - NetBeans.windowWithDebuggedTab = tab.windowId; - NetBeans.createContextMenu(tabId, tab.url); - }); - // detect viewport - NetBeans.detectViewPort(); + const attachment = chrome.debugger.attach({tabId}, '1.0'); + NetBeans.attachments.set(tabId, attachment); + attachment.then(async () => { + if (NetBeans.attachments.get(tabId) !== attachment) { + return; + } + NetBeans.debuggedTab = tabId; + const tab = await chrome.tabs.get(tabId).catch(() => null); + if (tab && NetBeans.attachments.get(tabId) === attachment) { + NetBeans.windowWithDebuggedTab = tab.windowId; + NetBeans.createContextMenu(tabId, tab.url); } + }).catch(error => { + if (NetBeans.attachments.get(tabId) === attachment) { + NetBeans.attachments.delete(tabId); + } + console.warn('Cannot attach NetBeans debugger:', error); }); }; @@ -77,10 +75,11 @@ NetBeans.browserDetachDebugger = function(tabId) { if (NetBeans.DEBUG) { console.log('debugger detaching from tab ' + tabId); } - chrome.debugger.detach({tabId : tabId}); + const attachment = NetBeans.attachments.get(tabId); + NetBeans.attachments.delete(tabId); + attachment?.then(() => chrome.debugger.detach({tabId})).catch(() => {}); chrome.contextMenus.removeAll(); if (NetBeans.debuggedTab === tabId) { - NetBeans.hidePageIcon(tabId); NetBeans.debuggedTab = null; NetBeans.windowWithDebuggedTab = null; } @@ -88,14 +87,8 @@ NetBeans.browserDetachDebugger = function(tabId) { // display NB icon in URL bar NetBeans.showPageIcon = function(tabId) { - chrome.pageAction.show(tabId); -}; -NetBeans.hidePageIcon = function(tabId) { -// Do not hide page icon. The tab is managed still and the page icon -// can be used to reconnect to IDE. -// chrome.pageAction.hide(tabId); + chrome.action.enable(tabId).catch(() => {}); }; - // Creates the Select Mode context menu NetBeans.createContextMenu = function(tabId, url) { if (NetBeans.debuggedTab !== tabId) { @@ -121,10 +114,7 @@ NetBeans.createContextMenu = function(tabId, url) { id: 'selectionMode', title: NetBeans.contextMenuName(), contexts: ['all'], - documentUrlPatterns: [NetBeans.contextMenuUrl], - onclick: function() { - NetBeans.setSelectionMode(!NetBeans.getSelectionMode()); - } + documentUrlPatterns: [NetBeans.contextMenuUrl] }, function() { NetBeans.contextMenuCreationInProgress = false; @@ -144,16 +134,6 @@ NetBeans.contextMenuName = function() { return chrome.i18n.getMessage(NetBeans.getSelectionMode() ? '_StopSelectMode' : '_StartSelectMode'); }; -// show infobar -NetBeans.showInfoBar = function(tabId) { - chrome.experimental.infobars.show({ - tabId : tabId, - path: 'html/infobar.html' - }); -}; -NetBeans.getWindowInfo = function(callback) { - chrome.windows.getLastFocused({ populate: true }, callback); -}; NetBeans.detectViewPort = function(callback) { if (NetBeans.debuggedTab === null) { console.log('No debuggedTab so bypassing the detection'); @@ -162,18 +142,22 @@ NetBeans.detectViewPort = function(callback) { } return; } - var script = 'NetBeans_ViewPort = {' + var script = '({' + ' width: window.innerWidth,' + ' height: window.innerHeight,' + ' marginWidth: window.outerWidth - window.innerWidth,' + ' marginHeight: window.outerHeight - window.innerHeight,' + ' isMac: navigator.platform.toUpperCase().indexOf("MAC") !== -1' - + '};'; + + '})'; chrome.debugger.sendCommand( {tabId : NetBeans.debuggedTab}, 'Runtime.evaluate', {expression: script, returnByValue: true}, function(result) { + if (chrome.runtime.lastError || !result?.result?.value) { + callback?.(); + return; + } var viewport = result.result.value; NetBeans_ViewPort.width = viewport.width; NetBeans_ViewPort.height = viewport.height; @@ -231,53 +215,38 @@ NetBeans._resizePage = function(width, height, callback) { }); }); }; -// show preset customizer -NetBeans.showPresetCustomizer = function() { - chrome.tabs.create({'url': 'html/options.html'}); -}; - -NetBeans.browserSendCommand = function(tabId, id, method, params, callback) { - if (NetBeans.DEBUG) { - console.log('send ['+tabId+","+id+","+method+","+JSON.stringify(params)); +NetBeans.browserSendCommand = async function(tabId, id, method, params) { + const attachment = NetBeans.attachments.get(tabId); + const socket = NetBeans.socket; + let response; + try { + if (!attachment) { + throw new Error('Debugger is not attached.'); + } + await attachment; + if (NetBeans.attachments.get(tabId) !== attachment) { + throw new Error('Debugger was detached.'); + } + const result = await chrome.debugger.sendCommand({tabId}, method, params); + response = {id, result: result || {}}; + } catch (error) { + response = {id, error: JSON.stringify({message: error.message})}; } - chrome.debugger.sendCommand({tabId : tabId}, method, params, - function(result) { - if (chrome.runtime.lastError) { - var error = JSON.stringify(chrome.runtime.lastError); - console.log('debugger send command result code: ' + error); - NetBeans.sendDebuggingResponse(tabId, {id : id, error : error}); - } else { - console.log('debugger send command response: ' + result); - NetBeans.sendDebuggingResponse(tabId, {id : id, result : result}); - } - }); -}; - -// "fired" when presets changed -NetBeans_Presets.presetsChanged = function() { - // no need to refresh popup, refresh only infobar(s) - var views = chrome.extension.getViews({type: "infobar"}); - console.log('Refreshing ' + views.length + ' infobars'); - for (var i in views) { - var view = views[i]; - view.NetBeans_Infobar.redrawPresets(); + if (NetBeans.socketReady && NetBeans.socket === socket) { + NetBeans.sendDebuggingResponse(tabId, response); } }; -// Updates the context menu and the info-bar according to changes of page-inspection properties -NetBeans.addPageInspectionPropertyListener(function(event) { - var name = event.name; - if (name !== 'selectionMode') { - return; +chrome.contextMenus.onClicked.addListener((info, tab) => { + if (info.menuItemId === 'selectionMode' && tab?.id === NetBeans.debuggedTab + && NetBeans.socketReady) { + NetBeans.setSelectionMode(!NetBeans.getSelectionMode()); } - NetBeans.updateContextMenu(); - var value = event.value; - var views = chrome.extension.getViews({type: "infobar"}); - for (var i in views) { - var view = views[i]; - if (view.NetBeans_Infobar) { - view.NetBeans_Infobar.setSelectionMode(value); - } +}); + +NetBeans.addPageInspectionPropertyListener(event => { + if (event.name === 'selectionMode' && NetBeans.debuggedTab !== null) { + NetBeans.updateContextMenu(); } }); @@ -343,10 +312,15 @@ NetBeans.openPopup = function(url, width, height) { }; chrome.debugger.onEvent.addListener(function(source, method, params) { - NetBeans.sendDebuggingResponse(source.tabId, {method : method, params : params}); + if (NetBeans.socketReady && NetBeans.attachments.has(source.tabId)) { + NetBeans.sendDebuggingResponse(source.tabId, {method : method, params : params}); + } }); chrome.debugger.onDetach.addListener(function(source, reason) { + if (!NetBeans.attachments.delete(source.tabId)) { + return; + } NetBeans._checkUnexpectedDetach(source.tabId, reason); chrome.contextMenus.removeAll(); if (source.tabId === NetBeans.debuggedTab) { @@ -361,31 +335,14 @@ chrome.tabs.onCreated.addListener(function(tab) { NetBeans.tabCreated(tab.id); }); chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { - NetBeans.tabUpdated(tab); + if (changeInfo.url || changeInfo.status === 'complete') { + NetBeans.tabUpdated(tab); + } }); chrome.tabs.onRemoved.addListener(function(tabId) { NetBeans.tabRemoved(tabId); }); -// onCreated event is not delivered for the first tab; -// As a workaround, we go through all existing tabs and consider them as new. -// onUpdated event is not delivered sometimes as well for the first tab; -// Hence, we consider also tab urls that are known already. -chrome.windows.getAll({populate: true}, function(windows) { - for (var i=0; i { + clearInterval(this.heartbeat); + this.cleanup(); + for (const tabId of Object.keys(this.managedTabs)) { + chrome.action.disable(Number(tabId)).catch(() => {}); } - self.cleanup(); + this.managedTabs = {}; + ResizeOptions = null; + NetBeans_Presets._presets = null; + this.selectionMode = false; + this.disconnectDebugger(); + this.reconnect = setTimeout(() => this.connectIfNeeded(), 3000); }; - this.socket.onclose = function() { - self.cleanup(); - }; - this.socket.onopen = function() { - self.socketReady = true; - self.sendPendingMessages(); + socket.onopen = () => { + clearTimeout(this.reconnect); + this.socketReady = true; + this.sendReadyMessage(chrome.runtime.getManifest().version); + this.sendLoadResizeOptionsMessage(); + chrome.tabs.query({}).then(tabs => { + if (this.socket === socket && this.socketReady) { + tabs.forEach(tab => this.tabUpdated(tab)); + } + }); + this.heartbeat = setInterval(() => this.sendMessage({ + message: 'load_resize_options' + }), 20000); }; this.socket.onmessage = function(e) { if (NetBeans.DEBUG) { @@ -98,7 +105,9 @@ NetBeans.connectIfNeeded = function() { console.log(e.data); return; } - self.processMessage(message); + if (message && typeof message.message === 'string') { + self.processMessage(message); + } }; } return this.socketReady; @@ -111,9 +120,9 @@ NetBeans.sendMessage = function(message) { console.log('Sent message: ' + messageText); } this.socket.send(messageText); - } else { - this.pendingMessages.push(message); + return true; } + return false; }; NetBeans.sendReadyMessage = function(version) { @@ -172,25 +181,10 @@ NetBeans.sendSelectionModeMessage = function(selectionMode) { }); }; -NetBeans.sendPendingMessages = function() { - for (var i=0; i {}); } } else { console.log('Ignoring init message for a tab for which such message was not requested: '+tabId); @@ -329,6 +325,7 @@ NetBeans.processDebuggerCommandMessage = function(message) { NetBeans.processLoadResizeOptionsMessage = function(message) { ResizeOptions = JSON.parse(message.resizeOptions); + NetBeans_Presets._presets = null; }; NetBeans.processSaveResizeOptionsMessage = function(message) { @@ -379,9 +376,20 @@ NetBeans.tabCreated = function(tabId) { }; NetBeans.tabUpdated = function(tab) { + if (!/^(https?:|file:)/.test(tab.url || '')) { + return; + } + const previous = this.managedTabs[tab.id]; + if (!previous || (previous.status === this.STATUS_NOT_MANAGED && previous.url !== tab.url)) { + this.tabCreated(tab.id); + } var status = this.tabStatus(tab.id); var tabInfo = this.managedTabs[tab.id]; if (status === this.STATUS_NEW) { + if (!this.socketReady) { + this.connectIfNeeded(); + return; + } tabInfo.status = this.STATUS_UNCONFIRMED; tabInfo.url = tab.url; // Send URL to IDE - ask if the tab is managed @@ -402,9 +410,6 @@ NetBeans.tabUpdated = function(tab) { } this.showPageIcon(tab.id); this.createContextMenu(tab.id, tab.url); - if (this.INFOBAR) { - this.showInfoBar(tab.id); - } } } }; @@ -439,84 +444,6 @@ NetBeans.getSynchronizeSelection = function() { return this.synchronizeSelection; }; -/** - * Class representing window preset. - * - * Internal presets cannot be removed. - */ -function NetBeans_Preset(type, displayName, width, height, showInToolbar, isDefault) { - // type (its ident) - this.type = type; - // display name - this.displayName = displayName; - // width (in px) - this.width = width; - // height (in px) - this.height = height; - // show in toolbar - this.showInToolbar = showInToolbar; - // default or not? - this.isDefault = isDefault; -} -// preset type for Desktops -NetBeans_Preset.DESKTOP = { - ident: 'DESKTOP', - title: I18n.message('_Desktop') -}; -// preset type for Netbooks -NetBeans_Preset.NETBOOK = { - ident: 'NETBOOK', - title: I18n.message('_Netbook') -}; -NetBeans_Preset.WIDESCREEN = { - ident: 'WIDESCREEN', - title: I18n.message('_Widescreen') -}; -// preset type for Tablets (Landscape) -NetBeans_Preset.TABLET_LANDSCAPE = { - ident: 'TABLET_LANDSCAPE', - title: I18n.message('_TabletLandscape') -}; -// preset type for Tablets (Portrait) -NetBeans_Preset.TABLET_PORTRAIT = { - ident: 'TABLET_PORTRAIT', - title: I18n.message('_TabletPortrait') -}; -// preset type for Smartphones (Landscape) -NetBeans_Preset.SMARTPHONE_LANDSCAPE = { - ident: 'SMARTPHONE_LANDSCAPE', - title: I18n.message('_SmartphoneLandscape') -}; -// preset type for Smartphones (Portrait) -NetBeans_Preset.SMARTPHONE_PORTRAIT = { - ident: 'SMARTPHONE_PORTRAIT', - title: I18n.message('_SmartphonePortrait') -}; -// get a list of all preset types -NetBeans_Preset.allTypes = function() { - return [ - NetBeans_Preset.DESKTOP, - NetBeans_Preset.NETBOOK, - NetBeans_Preset.WIDESCREEN, - NetBeans_Preset.TABLET_LANDSCAPE, - NetBeans_Preset.TABLET_PORTRAIT, - NetBeans_Preset.SMARTPHONE_LANDSCAPE, - NetBeans_Preset.SMARTPHONE_PORTRAIT - ]; -}; -// get preset type for the given ident, or null if not found -NetBeans_Preset.typeForIdent = function(ident) { - var allTypes = NetBeans_Preset.allTypes(); - for (i in allTypes) { - if (allTypes[i].ident === ident) { - return allTypes[i]; - } - } - console.error('Type not found for ident: ' + ident); - // fallback, avoid NPE - return allTypes[0]; -}; - /** * Window presets manager. */ @@ -529,7 +456,7 @@ NetBeans_Presets.getPreset = function(preset) { if (preset === undefined) { return this._preset; } - var tmp = this.getPresets()[preset]; + var tmp = this.getPresets()?.[preset]; if (tmp === undefined) { return null; } @@ -550,7 +477,6 @@ NetBeans_Presets.getPresets = function(copy) { NetBeans_Presets.setPresets = function(presets) { this._presets = presets; this._savePresets(); - this.presetsChanged(); }; // load presets from the central storage NetBeans_Presets._loadPresets = function() { diff --git a/webcommon/extbrowser.chrome/plugins/chrome/js/devtools-nb.js b/webcommon/extbrowser.chrome/plugins/chrome/js/devtools-nb.js index b9cef23ef9c1..354a4def9cd6 100644 --- a/webcommon/extbrowser.chrome/plugins/chrome/js/devtools-nb.js +++ b/webcommon/extbrowser.chrome/plugins/chrome/js/devtools-nb.js @@ -17,43 +17,10 @@ * under the License. */ -var NetBeans_Panel = {}; - -NetBeans_Panel._backgroundPageConnection = null; -NetBeans_Panel._propagateChangesCheckbox = null; - -NetBeans_Panel.init = function() { - if (NetBeans_Panel._backgroundPageConnection !== null) { - return; - } - this._backgroundPageConnection = chrome.runtime.connect(); - this._propagateChangesCheckbox = document.getElementById('propagateChangesCheckbox'); - this._registerEvents(); - this._load(); -}; -// register events -NetBeans_Panel._registerEvents = function() { - var that = this; - this._backgroundPageConnection.onMessage.addListener(function(message) { - if (message.enabled !== undefined) { - that._propagateChangesCheckbox.checked = message.enabled; - } +window.addEventListener('load', async () => { + const checkbox = document.getElementById('propagateChangesCheckbox'); + checkbox.checked = await chrome.runtime.sendMessage({action: 'getWriteBack'}); + checkbox.addEventListener('change', () => { + chrome.runtime.sendMessage({action: 'setWriteBack', value: checkbox.checked}); }); - this._propagateChangesCheckbox.addEventListener('change', function() { - that._backgroundPageConnection.postMessage({ - event: 'setChangesPropagated', - enabled: that._propagateChangesCheckbox.checked - }); - }, false); -}; -// load initial state -NetBeans_Panel._load = function() { - this._backgroundPageConnection.postMessage({ - event: 'areChangesPropagated' - }); -}; - -// run! -window.addEventListener('load', function() { - NetBeans_Panel.init(); -}, false); +}); diff --git a/webcommon/extbrowser.chrome/plugins/chrome/js/devtools.js b/webcommon/extbrowser.chrome/plugins/chrome/js/devtools.js index 2da2223ea444..7356094db55f 100644 --- a/webcommon/extbrowser.chrome/plugins/chrome/js/devtools.js +++ b/webcommon/extbrowser.chrome/plugins/chrome/js/devtools.js @@ -17,15 +17,13 @@ * under the License. */ -// references from bg page -var backgroundPageConnection = chrome.runtime.connect(); - -chrome.devtools.inspectedWindow.onResourceContentCommitted.addListener(function(resource, content) { - backgroundPageConnection.postMessage({ - event: 'onResourceContentCommitted', - resource: resource, - content: content - }); +chrome.devtools.inspectedWindow.onResourceContentCommitted.addListener((resource, content) => { + chrome.runtime.sendMessage({ + action: 'resourceCommitted', + tabId: chrome.devtools.inspectedWindow.tabId, + resource: {url: resource.url, type: resource.type}, + content + }).catch(() => {}); }); -chrome.devtools.panels.create('NetBeans', '../img/presets/netbeans16.png', '../html/devtools-nb.html'); +chrome.devtools.panels.create('NetBeans', '../img/netbeans16.png', '../html/devtools-nb.html'); diff --git a/webcommon/extbrowser.chrome/plugins/chrome/js/infobar.js b/webcommon/extbrowser.chrome/plugins/chrome/js/infobar.js deleted file mode 100644 index cad265c1ae4a..000000000000 --- a/webcommon/extbrowser.chrome/plugins/chrome/js/infobar.js +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// references from bg page -var NetBeans = chrome.extension.getBackgroundPage().NetBeans; -var NetBeans_Presets = chrome.extension.getBackgroundPage().NetBeans_Presets; - -/** - * Infobar. - */ -var NetBeans_Infobar = {}; -// presets -NetBeans_Infobar._presets = null; -// preset container -NetBeans_Infobar._container = null; -// show presets -NetBeans_Infobar.show = function(presets) { - this._presets = presets; - this._init(); - this.setSelectionMode(NetBeans.getSelectionMode()); - this._showPresets(); -}; -// redraw presets -NetBeans_Infobar.redrawPresets = function() { - this.show(NetBeans_Presets.getPresets()); -}; -// init -NetBeans_Infobar._init = function() { - if (this._container !== null) { - return; - } - this._container = document.getElementById('presets'); - this._registerEvents(); -}; -// register events -NetBeans_Infobar._registerEvents = function() { - var that = this; - document.getElementById('autoPresetButton').addEventListener('click', function() { - NetBeans.resetPageSize(); - }, false); - document.getElementById('presetCustomizerButton').addEventListener('click', function() { - NetBeans.showPresetCustomizer(); - }, false); - document.getElementById('selectionModeCheckBox').addEventListener('click', function() { - that._updateSelectionMode(false); - }, false); - document.getElementById('selectionModeMenu').addEventListener('click', function() { - that._updateSelectionMode(true); - }, false); -}; -// show presets in the toolbar -NetBeans_Infobar._showPresets = function() { - // clean - this._container.innerHTML = ''; - // add buttons - for (var p in this._presets) { - var preset = this._presets[p]; - if (!preset.showInToolbar) { - continue; - } - var button = document.createElement('a'); - button.setAttribute('href', '#'); - button.setAttribute('class', 'button'); - button.setAttribute('title', preset.displayName + ' (' + preset.width + ' x ' + preset.height + ')'); - // wrap function to another function so current index is copied (otherwise, the last index will be always used) - button.addEventListener('click', function(presetIndex) { - return function() { - NetBeans.resizePage(presetIndex); - }; - } (p), false); - button.appendChild(document.createTextNode(preset.displayName)); - this._container.appendChild(button); - } -}; - -NetBeans_Infobar._updateSelectionMode = function(switchCheckBoxValue) { - var checkbox = document.getElementById('selectionModeCheckBox'); - if (switchCheckBoxValue) { - checkbox.checked = !checkbox.checked; - } - var selectionMode = checkbox.checked; - NetBeans.setSelectionMode(selectionMode); -}; - -// Modifies Selection Mode checkbox according to the given value -NetBeans_Infobar.setSelectionMode = function(selectionMode) { - var checkbox = document.getElementById('selectionModeCheckBox'); - checkbox.checked = selectionMode; -}; - -// run! -window.addEventListener('load', function() { - NetBeans_Infobar.show(NetBeans_Presets.getPresets()); -}, false); diff --git a/webcommon/extbrowser.chrome/plugins/chrome/js/options.js b/webcommon/extbrowser.chrome/plugins/chrome/js/options.js index 414d07622b9b..53549ad98afb 100644 --- a/webcommon/extbrowser.chrome/plugins/chrome/js/options.js +++ b/webcommon/extbrowser.chrome/plugins/chrome/js/options.js @@ -18,11 +18,6 @@ */ // references from bg page -var INFOBAR = chrome.extension.getBackgroundPage().NetBeans.INFOBAR; -var NetBeans_Presets = chrome.extension.getBackgroundPage().NetBeans_Presets; -var NetBeans_Preset = chrome.extension.getBackgroundPage().NetBeans_Preset; -var NetBeans_Warnings = chrome.extension.getBackgroundPage().NetBeans_Warnings; - /** * Preset customizer. */ @@ -61,9 +56,7 @@ NetBeans_PresetCustomizer._init = function() { if (this._rowContainer !== null) { return; } - if (!INFOBAR) { - document.getElementById('toolbarHeader').style.display = 'none'; - } + document.getElementById('toolbarHeader').style.display = 'none'; this._moreHelpButton = document.getElementById('moreHelpButton'); this._rowContainer = document.getElementById('presetCustomizerTable').getElementsByTagName('tbody')[0]; this._addPresetButton = document.getElementById('addPreset'); @@ -183,21 +176,6 @@ NetBeans_PresetCustomizer._putPresetsInternal = function(presets) { }, false); height.appendChild(heightInput); row.appendChild(height); - // toolbar - if (INFOBAR) { - var toolbar = document.createElement('td'); - toolbar.setAttribute('class', 'toolbar'); - var toolbarCheckbox = document.createElement('input'); - toolbarCheckbox.setAttribute('type', 'checkbox'); - if (preset.showInToolbar) { - toolbarCheckbox.setAttribute('checked', 'checked'); - } - toolbarCheckbox.addEventListener('click', function() { - that._toolbarChanged(this); - }, false); - toolbar.appendChild(toolbarCheckbox); - row.appendChild(toolbar); - } // append row this._rowContainer.appendChild(row); preset['_row'] = row; @@ -259,13 +237,15 @@ NetBeans_PresetCustomizer._movePreset = function(preset, shift) { this._presets[index + shift] = tmp; }; // save presets to the central storage and redraw them -NetBeans_PresetCustomizer._save = function() { +NetBeans_PresetCustomizer._save = async function() { for (i in this._presets) { var preset = this._presets[i]; delete preset['_row']; delete preset['_errors']; } - NetBeans_Presets.setPresets(this._presets); + if (!await chrome.runtime.sendMessage({action: 'savePresets', value: this._presets})) { + return; + } this._cleanUp(); this._hide(); }; @@ -283,7 +263,7 @@ NetBeans_PresetCustomizer._switchHelp = function() { }; // reset warnings NetBeans_PresetCustomizer._resetWarnings = function() { - NetBeans_Warnings.reset(); + chrome.runtime.sendMessage({action: 'resetWarnings'}); this._resetWarningsButton.innerHTML = I18n.message('_Done'); this._resetWarningsButton.setAttribute('disabled', 'disabled'); }; @@ -397,10 +377,6 @@ NetBeans_PresetCustomizer._heightChanged = function(input) { }); }; // callback when preset toolbar changes -NetBeans_PresetCustomizer._toolbarChanged = function(input) { - this._activePreset.showInToolbar = input.checked; -}; -// check whether the value is not empty NetBeans_PresetCustomizer._validateNotEmpty = function(value) { return value != null && value.trim().length > 0; }; @@ -452,6 +428,6 @@ function nbRemoveCssClass(element, cssClass) { } // run! -window.addEventListener('load', function() { - NetBeans_PresetCustomizer.show(NetBeans_Presets.getPresets(true)); +window.addEventListener('load', async function() { + NetBeans_PresetCustomizer.show(await chrome.runtime.sendMessage({action: 'presets'})); }, false); diff --git a/webcommon/extbrowser.chrome/plugins/chrome/js/popup.js b/webcommon/extbrowser.chrome/plugins/chrome/js/popup.js index 0888b494d6e1..40ccd32be30f 100644 --- a/webcommon/extbrowser.chrome/plugins/chrome/js/popup.js +++ b/webcommon/extbrowser.chrome/plugins/chrome/js/popup.js @@ -18,11 +18,6 @@ */ // references from bg page -var NetBeans = chrome.extension.getBackgroundPage().NetBeans; -var NetBeans_Presets = chrome.extension.getBackgroundPage().NetBeans_Presets; -var NetBeans_Preset = chrome.extension.getBackgroundPage().NetBeans_Preset; -var NetBeans_ViewPort = chrome.extension.getBackgroundPage().NetBeans_ViewPort; - /** * Window presets menu. */ @@ -31,6 +26,13 @@ var NetBeans_PresetMenu = {}; NetBeans_PresetMenu._container = null; // menu presets NetBeans_PresetMenu._presets = null; +let popupState; +let activeTab; + +function runAction(action, value) { + chrome.runtime.sendMessage({action, value, tabId: activeTab.id}) + .then(() => window.close()); +} // show the menu NetBeans_PresetMenu.show = function(presets, activeTab) { this._init(activeTab); @@ -43,16 +45,10 @@ NetBeans_PresetMenu.hide = function() { window.close(); }; NetBeans_PresetMenu.resetPage = function() { - var that = this; - NetBeans.resetPageSize(function() { - that.hide(); - }); + runAction('resize', null); }; NetBeans_PresetMenu.resizePage = function(preset) { - var that = this; - NetBeans.resizePage(preset, function() { - that.hide(); - }); + runAction('resize', preset); }; NetBeans_PresetMenu.setAutoPresetActive = function() { document.getElementById('autoPresetMenu').setAttribute('class', 'active'); @@ -70,9 +66,9 @@ NetBeans_PresetMenu._init = function(activeTab) { // selection mode init NetBeans_PresetMenu._initSelectionMode = function(activeTab) { var selectionMode = document.getElementById('selectionModeCheckBox'); - selectionMode.checked = NetBeans.getSelectionMode(); + selectionMode.checked = popupState.selectionMode; var selectionModeMenu = document.getElementById('selectionModeMenu'); - var display = NetBeans.debuggedTab === activeTab.id ? 'block' : 'none'; + var display = popupState.debuggedTab === activeTab.id ? 'block' : 'none'; selectionModeMenu.style.display = display; var selectionModeSeparator = document.getElementById('selectionModeSeparator'); if (selectionModeSeparator) { @@ -82,7 +78,7 @@ NetBeans_PresetMenu._initSelectionMode = function(activeTab) { // Debug in NetBeans init NetBeans_PresetMenu._initDebugInNetBeans = function(activeTab) { var menu = document.getElementById('debugInNetBeansMenu'); - var display = NetBeans.ideVersion === "7.4" || NetBeans.debuggedTab === activeTab.id ? 'none' : 'block'; + var display = popupState.ideVersion === "7.4" || popupState.debuggedTab === activeTab.id ? 'none' : 'block'; menu.style.display = display; var separator = document.getElementById('debugInNetBeansSeparator'); if (separator) { @@ -102,7 +98,7 @@ NetBeans_PresetMenu._registerEvents = function(activeTab) { that._updateSelectionMode(event.target.id !== 'selectionModeCheckBox'); }, false); document.getElementById('debugInNetBeansMenu').addEventListener('click', function() { - that._debugInNetBeans(activeTab); + runAction('inspect'); }, false); }; // clean and put presets to the menu @@ -112,7 +108,7 @@ NetBeans_PresetMenu._putPresets = function() { menu.innerHTML = ''; for (var p in this._presets) { var preset = this._presets[p]; - var activePreset = NetBeans_ViewPort.width == preset.width && NetBeans_ViewPort.height == preset.height; + var activePreset = popupState.viewport.width == preset.width && popupState.viewport.height == preset.height; // item var item = document.createElement('a'); item.setAttribute('href', '#'); @@ -168,8 +164,7 @@ NetBeans_PresetMenu._putPresets = function() { }; // show preset customizer NetBeans_PresetMenu._showPresetCustomizer = function() { - NetBeans.showPresetCustomizer(); - this.hide(); + chrome.runtime.openOptionsPage().then(() => this.hide()); }; NetBeans_PresetMenu._updateSelectionMode = function(switchCheckBoxValue) { @@ -178,36 +173,18 @@ NetBeans_PresetMenu._updateSelectionMode = function(switchCheckBoxValue) { checkbox.checked = !checkbox.checked; } var selectionMode = checkbox.checked; - NetBeans.setSelectionMode(selectionMode); - this.hide(); + runAction('selection', selectionMode); }; -NetBeans_PresetMenu._debugInNetBeans = function(activeTab) { - NetBeans.sendMessage({ - message: 'inspect', - tabId: activeTab.id, - url: activeTab.url - }); - this.hide(); -}; - -// run! -window.addEventListener('load', function() { - NetBeans.detectViewPort(function() { - NetBeans.getWindowInfo(function(window) { - var activeTab = null; - var i; - for (i=0; i { + [activeTab] = await chrome.tabs.query({active: true, currentWindow: true}); + if (!activeTab) { + return; + } + popupState = await chrome.runtime.sendMessage({action: 'popup', tabId: activeTab.id}); + NetBeans_PresetMenu.show(popupState.presets || [], activeTab); + const windowInfo = await chrome.windows.get(activeTab.windowId); + if (windowInfo.state === 'maximized') { + NetBeans_PresetMenu.setAutoPresetActive(); + } +}); diff --git a/webcommon/extbrowser.chrome/plugins/chrome/js/preset.js b/webcommon/extbrowser.chrome/plugins/chrome/js/preset.js new file mode 100644 index 000000000000..ff515e87657b --- /dev/null +++ b/webcommon/extbrowser.chrome/plugins/chrome/js/preset.js @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Class representing window preset. + * + * Internal presets cannot be removed. + */ +function NetBeans_Preset(type, displayName, width, height, showInToolbar, isDefault) { + // type (its ident) + this.type = type; + // display name + this.displayName = displayName; + // width (in px) + this.width = width; + // height (in px) + this.height = height; + // show in toolbar + this.showInToolbar = showInToolbar; + // default or not? + this.isDefault = isDefault; +} +// preset type for Desktops +NetBeans_Preset.DESKTOP = { + ident: 'DESKTOP', + title: I18n.message('_Desktop') +}; +// preset type for Netbooks +NetBeans_Preset.NETBOOK = { + ident: 'NETBOOK', + title: I18n.message('_Netbook') +}; +NetBeans_Preset.WIDESCREEN = { + ident: 'WIDESCREEN', + title: I18n.message('_Widescreen') +}; +// preset type for Tablets (Landscape) +NetBeans_Preset.TABLET_LANDSCAPE = { + ident: 'TABLET_LANDSCAPE', + title: I18n.message('_TabletLandscape') +}; +// preset type for Tablets (Portrait) +NetBeans_Preset.TABLET_PORTRAIT = { + ident: 'TABLET_PORTRAIT', + title: I18n.message('_TabletPortrait') +}; +// preset type for Smartphones (Landscape) +NetBeans_Preset.SMARTPHONE_LANDSCAPE = { + ident: 'SMARTPHONE_LANDSCAPE', + title: I18n.message('_SmartphoneLandscape') +}; +// preset type for Smartphones (Portrait) +NetBeans_Preset.SMARTPHONE_PORTRAIT = { + ident: 'SMARTPHONE_PORTRAIT', + title: I18n.message('_SmartphonePortrait') +}; +// get a list of all preset types +NetBeans_Preset.allTypes = function() { + return [ + NetBeans_Preset.DESKTOP, + NetBeans_Preset.NETBOOK, + NetBeans_Preset.WIDESCREEN, + NetBeans_Preset.TABLET_LANDSCAPE, + NetBeans_Preset.TABLET_PORTRAIT, + NetBeans_Preset.SMARTPHONE_LANDSCAPE, + NetBeans_Preset.SMARTPHONE_PORTRAIT + ]; +}; +// get preset type for the given ident, or null if not found +NetBeans_Preset.typeForIdent = function(ident) { + var allTypes = NetBeans_Preset.allTypes(); + for (i in allTypes) { + if (allTypes[i].ident === ident) { + return allTypes[i]; + } + } + console.error('Type not found for ident: ' + ident); + // fallback, avoid NPE + return allTypes[0]; +}; diff --git a/webcommon/extbrowser.chrome/plugins/chrome/js/warning.js b/webcommon/extbrowser.chrome/plugins/chrome/js/warning.js index 4929d1c31863..96ff42c3fefe 100644 --- a/webcommon/extbrowser.chrome/plugins/chrome/js/warning.js +++ b/webcommon/extbrowser.chrome/plugins/chrome/js/warning.js @@ -18,7 +18,6 @@ */ // references from bg page -var NetBeans_Warnings = chrome.extension.getBackgroundPage().NetBeans_Warnings; /** * Warning - the content is set by the URL ident (accessible via window.location.hash). @@ -55,7 +54,11 @@ NetBeans_Warning._close = function() { window.close(); }; NetBeans_Warning._doNotShowAgain = function() { - NetBeans_Warnings.enable(this._ident, !this._doNotShowAgainButton.checked); + chrome.runtime.sendMessage({ + action: 'setWarning', + ident: this._ident, + value: !this._doNotShowAgainButton.checked + }); }; // run! diff --git a/webcommon/extbrowser.chrome/plugins/chrome/manifest.json b/webcommon/extbrowser.chrome/plugins/chrome/manifest.json index a5d74d44d825..9fd56aa121f5 100644 --- a/webcommon/extbrowser.chrome/plugins/chrome/manifest.json +++ b/webcommon/extbrowser.chrome/plugins/chrome/manifest.json @@ -1,42 +1,36 @@ { "name": "__MSG__pluginName__", "description": "__MSG__pluginDescription__", - "manifest_version": 2, - "minimum_chrome_version": "21", - - "version": "1.1.5", - + "manifest_version": 3, + "minimum_chrome_version": "120", + "version": "1.1.6", "homepage_url": "https://chrome.google.com/webstore/detail/netbeans-connector/hafdlehgocfcodbgjnpecfajgkeejnaa", - "background": { - "page": "html/main.html" + "service_worker": "js/background.js" }, - "devtools_page": "html/devtools.html", - "options_page": "html/options.html", - - "page_action": { - "default_icon": "img/netbeans16.png", - "default_title": "Open NetBeans actions", - "default_popup": "html/popup.html" - }, - "permissions": [ "contextMenus", "tabs", "debugger", - "storage" + "storage", + "alarms" ], - - "content_security_policy": "default-src 'self'; connect-src ws://127.0.0.1:8008/", - + "content_security_policy": { + "extension_pages": "script-src 'self'; object-src 'self'; connect-src ws://127.0.0.1:8008/" + }, "icons": { "16": "img/netbeans16.png", "48": "img/netbeans48.png", "128": "img/netbeans128.png" }, - - "default_locale": "en" - + "default_locale": "en", + "action": { + "default_state": "disabled", + "default_icon": "img/netbeans16.png", + "default_title": "Open NetBeans actions", + "default_popup": "html/popup.html" + }, + "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgo89CrO8f/2srD2BGUP9+dG4IkTC2D3gzEjXITaMaQgy8B4ObVpkA3bc27qc7HB9jhVj8P51aAETr89u+AvFgCeFtvtva0h0oodKRC3dCkQLnEWPGi7mEKB98cRhZmQ1Wa9A9tg3plKsujwwWskaFEL/hO7uu7myF0qLIeuiG6wIDAQAB" }