blob: 35cfd99edabdefddb7fdba33e889ed3e5aeb46c1 [file]
/*
* 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;