| /* |
| * 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. |
| */ |
| |
| NetBeans = new Object(); |
| |
| NetBeans.serverURL = function() { |
| var serverProtocol = 'ws'; |
| var serverHost = '127.0.0.1'; |
| var serverPort = 8008; |
| var serverFile = '/'; |
| return serverProtocol+'://'+serverHost+':'+serverPort+serverFile; |
| }; |
| |
| NetBeans.DEBUG = true; |
| NetBeans.INFOBAR = false; |
| |
| // Version that the extension reports to the IDE in 'init' message |
| NetBeans.VERSION = "1.8.1"; |
| // The last version that the IDE reported to the extension |
| NetBeans.ideVersion = null; |
| |
| NetBeans.managedTabs = new Object(); |
| |
| NetBeans.STATUS_NEW = 0; |
| NetBeans.STATUS_UNCONFIRMED = 1; |
| NetBeans.STATUS_MANAGED = 2; |
| NetBeans.STATUS_NOT_MANAGED = 3; |
| |
| NetBeans.selectionMode = false; |
| NetBeans.synchronizeSelection = false; |
| NetBeans.pageInspectionListeners = []; |
| |
| NetBeans.tabStatus = function(tabId) { |
| var tabInfo = this.managedTabs[tabId]; |
| var status; |
| if (tabInfo === undefined) { |
| status = this.STATUS_NOT_MANAGED; |
| } else { |
| status = tabInfo.status; |
| } |
| return status; |
| }; |
| |
| NetBeans.cleanup = function() { |
| this.socket = null; |
| this.socketReady = false; |
| this.pendingMessages = []; |
| }; |
| |
| NetBeans.connectIfNeeded = function() { |
| if (this.socket === null) { |
| var self = this; |
| if (typeof(WebSocket) === 'undefined') { |
| this.socket = new MozWebSocket(this.serverURL()); |
| } else { |
| this.socket = new WebSocket(this.serverURL()); |
| } |
| this.socket.onerror = function(e) { |
| console.log('Socket error!'); |
| if (e.name && e.message) { |
| console.log(e.name + ': ' + e.message); |
| } |
| self.cleanup(); |
| }; |
| this.socket.onclose = function() { |
| self.cleanup(); |
| }; |
| this.socket.onopen = function() { |
| self.socketReady = true; |
| self.sendPendingMessages(); |
| }; |
| this.socket.onmessage = function(e) { |
| if (NetBeans.DEBUG) { |
| console.log('Received message: ' + e.data); |
| } |
| var message; |
| try { |
| message = JSON.parse(e.data); |
| } catch (err) { |
| console.log('Message not in JSON format!'); |
| console.log(err); |
| console.log(e.data); |
| return; |
| } |
| self.processMessage(message); |
| }; |
| } |
| return this.socketReady; |
| }; |
| |
| NetBeans.sendMessage = function(message) { |
| if (this.connectIfNeeded()) { |
| var messageText = JSON.stringify(message); |
| if (this.DEBUG) { |
| console.log('Sent message: ' + messageText); |
| } |
| this.socket.send(messageText); |
| } else { |
| this.pendingMessages.push(message); |
| } |
| }; |
| |
| NetBeans.sendReadyMessage = function(version) { |
| this.sendMessage({ |
| message: 'ready', |
| version: version |
| }); |
| }; |
| |
| NetBeans.sendInitMessage = function(tab) { |
| this.sendMessage({ |
| message: 'init', |
| url: tab.url, |
| tabId: tab.id, |
| version: this.VERSION |
| }); |
| }; |
| |
| NetBeans.sendCloseMessage = function(tabId) { |
| this.sendMessage({ |
| message: 'close', |
| tabId: tabId |
| }); |
| }; |
| |
| NetBeans.sendUrlChangeMessage = function(tabId, url) { |
| this.sendMessage({ |
| message: 'urlchange', |
| tabId: tabId, |
| url: url |
| }); |
| }; |
| |
| NetBeans.sendLoadResizeOptionsMessage = function() { |
| // XXX message sent more than once |
| if (ResizeOptions !== null) { |
| return; |
| } |
| this.sendMessage({ |
| message: 'load_resize_options' |
| }); |
| }; |
| |
| NetBeans.sendSaveResizeOptionsMessage = function(presets) { |
| ResizeOptions = presets; |
| this.sendMessage({ |
| message: 'save_resize_options', |
| resizeOptions: ResizeOptions |
| }); |
| }; |
| |
| NetBeans.sendSelectionModeMessage = function(selectionMode) { |
| this.sendMessage({ |
| message: 'selection_mode', |
| selectionMode: selectionMode |
| }); |
| }; |
| |
| NetBeans.sendPendingMessages = function() { |
| for (var i=0; i<this.pendingMessages.length; i++) { |
| this.sendMessage(this.pendingMessages[i]); |
| } |
| this.pendingMessages = []; |
| }; |
| |
| chrome.extension.onMessage.addListener( |
| function(request, sender, sendResponse) { |
| if (request.event == "onResourceContentCommitted") { |
| console.log('Sending changes from CDT back to NetBeans'); |
| NetBeans.sendResourceChangedInCDT(request.resource, request.content); |
| } |
| }); |
| |
| NetBeans.sendResourceChangedInCDT = function(url, content) { |
| this.sendMessage({ |
| message: 'resource_changed', |
| resource: url, |
| content: content |
| }); |
| }; |
| |
| NetBeans.processMessage = function(message) { |
| var type = message.message; |
| if (type === 'init') { |
| this.processInitMessage(message); |
| } else if (type === 'reload') { |
| this.processReloadMessage(message); |
| } else if (type === 'close') { |
| this.processCloseMessage(message); |
| } else if (type === 'attach_debugger') { |
| this.selectionMode = false; |
| this.processAttachDebuggerMessage(message); |
| } else if (type === 'detach_debugger') { |
| this.processDetachDebuggerMessage(message); |
| } else if (type === 'debugger_command') { |
| this.processDebuggerCommandMessage(message); |
| } else if (type === 'load_resize_options') { |
| this.processLoadResizeOptionsMessage(message); |
| } else if (type === 'save_resize_options') { |
| this.processSaveResizeOptionsMessage(message); |
| } else if (type === 'pageInspectionPropertyChange') { |
| this.processPageInspectionPropertyChange(message); |
| } else { |
| console.log('Unsupported message!'); |
| console.log(message); |
| } |
| }; |
| |
| NetBeans.tabIdFromMessage = function(message) { |
| var tabIdValue = message.tabId; |
| var tabId; |
| if (typeof(tabIdValue) === 'number') { |
| tabId = tabIdValue; |
| } else if (typeof(tabIdValue) === 'string') { |
| tabId = parseInt(tabIdValue); |
| } else { |
| console.log('Missing/incorrect tabId attribute!'); |
| console.log(message); |
| } |
| return tabId; |
| }; |
| |
| NetBeans.processInitMessage = function(message) { |
| var tabId = this.tabIdFromMessage(message); |
| if (tabId !== undefined) { |
| var tabInfo = this.managedTabs[tabId]; |
| if (tabInfo === undefined) { |
| console.log('Ignoring init message for an unknown tab: '+tabId); |
| } else if (tabInfo.status === this.STATUS_UNCONFIRMED) { |
| if (message.status === 'accepted') { |
| // Tab should be managed |
| NetBeans.ideVersion = message.version; |
| if (tabInfo.closed) { |
| // Delayed confirmation request for already closed tab; |
| // for a tab whose URL changed |
| this.sendCloseMessage(tabId); |
| delete this.managedTabs[tabId]; |
| } else { |
| tabInfo.status = this.STATUS_MANAGED; |
| this.showPageIcon(tabId); |
| this.createContextMenu(tabId, tabInfo.url); |
| } |
| } else { |
| // Tab shouldn't be managed |
| delete this.managedTabs[tabId]; |
| } |
| } else { |
| console.log('Ignoring init message for a tab for which such message was not requested: '+tabId); |
| } |
| } |
| }; |
| |
| NetBeans.processReloadMessage = function(message) { |
| var tabId = this.tabIdFromMessage(message); |
| if (tabId !== undefined) { |
| var status = this.tabStatus(tabId); |
| if (status === this.STATUS_MANAGED) { |
| this.browserReloadCallback(tabId, message.url); |
| } else { |
| console.log('Refusing to reload tab that is not managed: '+tabId); |
| } |
| } |
| }; |
| |
| NetBeans.processCloseMessage = function(message) { |
| var tabId = this.tabIdFromMessage(message); |
| if (tabId !== undefined) { |
| var status = this.tabStatus(tabId); |
| if (status === this.STATUS_MANAGED) { |
| this.browserCloseCallback(tabId); |
| } else { |
| console.log('Refusing to close tab that is not managed: '+tabId); |
| } |
| } |
| }; |
| |
| NetBeans.processAttachDebuggerMessage = function(message) { |
| var tabId = this.tabIdFromMessage(message); |
| if (tabId !== undefined) { |
| var status = this.tabStatus(tabId); |
| if (status === this.STATUS_MANAGED) { |
| this.browserAttachDebugger(tabId); |
| } else { |
| console.log('Refusing to attach debugger to tab that is not managed: '+tabId); |
| } |
| } |
| }; |
| |
| NetBeans.processDetachDebuggerMessage = function(message) { |
| var tabId = this.tabIdFromMessage(message); |
| if (tabId !== undefined) { |
| var status = this.tabStatus(tabId); |
| if (status === this.STATUS_MANAGED) { |
| this.browserDetachDebugger(tabId); |
| } else { |
| console.log('Refusing to dettach debugger from tab that is not managed: '+tabId); |
| } |
| } |
| }; |
| |
| NetBeans.processDebuggerCommandMessage = function(message) { |
| var tabId = this.tabIdFromMessage(message); |
| if (tabId !== undefined) { |
| var status = this.tabStatus(tabId); |
| if (status === this.STATUS_MANAGED) { |
| var command = message.command; |
| this.browserSendCommand(tabId, command.id, command.method, command.params); |
| } else { |
| console.log('Refusing to send debugger command to tab that is not managed: '+tabId); |
| } |
| } |
| }; |
| |
| NetBeans.processLoadResizeOptionsMessage = function(message) { |
| ResizeOptions = JSON.parse(message.resizeOptions); |
| }; |
| |
| NetBeans.processSaveResizeOptionsMessage = function(message) { |
| this.sendMessage({ |
| message: 'save_resize_options', |
| resizeOptions: message.resizeOptions |
| }); |
| }; |
| |
| NetBeans.processPageInspectionPropertyChange = function(message) { |
| var name = message.propertyName; |
| var value = message.propertyValue; |
| if (name === 'selectionMode') { |
| this.selectionMode = value; |
| } else if (name === 'synchronizeSelection') { |
| this.synchronizeSelection = value; |
| } |
| for (var i=0; i<this.pageInspectionListeners.length; i++) { |
| this.pageInspectionListeners[i]({ |
| name: name, |
| value: value |
| }); |
| } |
| }; |
| |
| NetBeans.addPageInspectionPropertyListener = function(listener) { |
| this.pageInspectionListeners.push(listener); |
| }; |
| |
| NetBeans.sendDebuggingResponse = function(tabId, response) { |
| this.sendMessage({ |
| message: 'debugger_command_response', |
| tabId: tabId, |
| response : response |
| }); |
| }; |
| |
| NetBeans.sendDebuggerDetached = function(tabId) { |
| this.sendMessage({ |
| message: 'debugger_detached', |
| tabId: tabId |
| }); |
| }; |
| |
| |
| NetBeans.tabCreated = function(tabId) { |
| this.managedTabs[tabId] = {status: this.STATUS_NEW}; |
| }; |
| |
| NetBeans.tabUpdated = function(tab) { |
| var status = this.tabStatus(tab.id); |
| var tabInfo = this.managedTabs[tab.id]; |
| if (status === this.STATUS_NEW) { |
| tabInfo.status = this.STATUS_UNCONFIRMED; |
| tabInfo.url = tab.url; |
| // Send URL to IDE - ask if the tab is managed |
| this.sendInitMessage(tab); |
| this.sendLoadResizeOptionsMessage(); |
| } else if (tabInfo !== undefined) { |
| // URL change should not mean that tab was closed; it may notify |
| // IDE that different page is opened in the browser pane if such knowledge |
| // of such state is desirable. |
| if (status === this.STATUS_UNCONFIRMED) { |
| // Navigation in an unconfirmed tab |
| // Confirmation may be delayed; do nothing for now |
| } else if (status === this.STATUS_MANAGED) { |
| // Navigation in a managed tab => send "urlchange" message |
| if (tabInfo.url !== tab.url) { |
| this.sendUrlChangeMessage(tab.id, tab.url); |
| tabInfo.url = tab.url; |
| } |
| this.showPageIcon(tab.id); |
| this.createContextMenu(tab.id, tab.url); |
| if (this.INFOBAR) { |
| this.showInfoBar(tab.id); |
| } |
| } |
| } |
| }; |
| |
| NetBeans.tabRemoved = function(tabId) { |
| var status = this.tabStatus(tabId); |
| if (status === this.STATUS_UNCONFIRMED) { |
| // Unconfirmed tab was closed |
| // Confirmation may be delayed; Mark it such that we know that |
| // "close" message should be sent if such delayed confirmation arrives |
| this.managedTabs[tabId].closed = true; |
| } else if (status === this.STATUS_MANAGED) { |
| // Managed tab was closed => send "closed" message |
| this.sendCloseMessage(tabId); |
| } |
| if (status !== this.STATUS_UNCONFIRMED) { |
| // Remove the tab from the set of managed tabs (if it was there) |
| delete this.managedTabs[tabId]; |
| } |
| }; |
| |
| NetBeans.setSelectionMode = function(selectionMode) { |
| this.selectionMode = selectionMode; |
| this.sendSelectionModeMessage(selectionMode); |
| }; |
| |
| NetBeans.getSelectionMode = function() { |
| return this.selectionMode; |
| }; |
| |
| 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. |
| */ |
| var NetBeans_Presets = {}; |
| // all presets |
| NetBeans_Presets._presets = null; |
| // active/current preset |
| NetBeans_Presets._preset = null; |
| NetBeans_Presets.getPreset = function(preset) { |
| if (preset === undefined) { |
| return this._preset; |
| } |
| var tmp = this.getPresets()[preset]; |
| if (tmp === undefined) { |
| return null; |
| } |
| this._preset = tmp; |
| return this._preset; |
| }; |
| // get all presets |
| NetBeans_Presets.getPresets = function(copy) { |
| if (copy) { |
| return this._loadPresets(); |
| } |
| if (this._presets === null) { |
| this._presets = this._loadPresets(); |
| } |
| return this._presets; |
| }; |
| // set (and save) new presets |
| NetBeans_Presets.setPresets = function(presets) { |
| this._presets = presets; |
| this._savePresets(); |
| this.presetsChanged(); |
| }; |
| // load presets from the central storage |
| NetBeans_Presets._loadPresets = function() { |
| if (ResizeOptions === null) { |
| // netbeans not running? |
| return null; |
| } |
| console.log('Mapping window presets from NetBeans'); |
| var presets = []; |
| for (var i in ResizeOptions) { |
| var option = ResizeOptions[i]; |
| presets.push(new NetBeans_Preset( |
| option.type, |
| option.displayName, |
| option.width, |
| option.height, |
| option.showInToolbar, |
| option.isDefault |
| )); |
| } |
| return presets; |
| }; |
| // save presets to the central storage |
| NetBeans_Presets._savePresets = function() { |
| console.log('Saving window presets back to NetBeans'); |
| NetBeans.sendSaveResizeOptionsMessage(this._presets); |
| }; |
| |
| /** |
| * Viewport (so browser window can be correctly resized). |
| */ |
| NetBeans_ViewPort = { |
| width: -1, |
| height: -1, |
| marginWidth: 0, |
| marginHeight: 0, |
| isMac: false |
| }; |
| |
| /** |
| * Resize options (a.k.a. Windows Presets from NetBeans). |
| */ |
| var ResizeOptions = null; |