package org.ovirt.engine.ui.common.presenter.popup;
import org.ovirt.engine.core.common.businessentities.UsbPolicy;
import org.ovirt.engine.core.common.console.ConsoleOptions;
import org.ovirt.engine.ui.common.CommonApplicationConstants;
import org.ovirt.engine.ui.common.gin.AssetProvider;
import org.ovirt.engine.ui.common.presenter.AbstractModelBoundPopupPresenterWidget;
import org.ovirt.engine.ui.common.widget.HasEnabledWithHints;
import org.ovirt.engine.ui.uicommonweb.ConsoleOptionsFrontendPersister;
import org.ovirt.engine.ui.uicommonweb.ConsoleUtils;
import org.ovirt.engine.ui.uicommonweb.DynamicMessages;
import org.ovirt.engine.ui.uicommonweb.UICommand;
import org.ovirt.engine.ui.uicommonweb.models.ConsolePopupModel;
import org.ovirt.engine.ui.uicommonweb.models.ConsoleProtocol;
import org.ovirt.engine.ui.uicommonweb.models.VmConsoles;
import org.ovirt.engine.ui.uicommonweb.models.VmConsolesImpl;
import org.ovirt.engine.ui.uicommonweb.models.vms.ConsoleClient;
import org.ovirt.engine.ui.uicommonweb.models.vms.RdpConsoleModel;
import org.ovirt.engine.ui.uicommonweb.models.vms.SpiceConsoleModel;
import org.ovirt.engine.ui.uicommonweb.models.vms.VncConsoleModel;
import org.ovirt.engine.ui.uicompat.EventArgs;
import org.ovirt.engine.ui.uicompat.IEventListener;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.Window;
import com.google.inject.Inject;
import com.gwtplatform.dispatch.annotation.GenEvent;
public class ConsolePopupPresenterWidget extends AbstractModelBoundPopupPresenterWidget<ConsolePopupModel, ConsolePopupPresenterWidget.ViewDef> {
@GenEvent
public class ConsoleModelChanged { }
// long term todo - rewrite set***Visible to set***Enabled with descriptive tooltip if disabled
public interface ViewDef extends AbstractModelBoundPopupPresenterWidget.ViewDef<ConsolePopupModel> {
void setSpiceAvailable(boolean visible);
void setRdpAvailable(boolean visible);
void setVncAvailable(boolean visible);
HasValueChangeHandlers<Boolean> getSpiceRadioButton();
HasValueChangeHandlers<Boolean> getRdpRadioButton();
HasValueChangeHandlers<Boolean> getVncRadioButton();
HasValueChangeHandlers<Boolean> getSpiceAutoImplRadioButton();
HasValueChangeHandlers<Boolean> getSpiceNativeImplRadioButton();
HasValueChangeHandlers<Boolean> getSpiceHtml5ImplRadioButton();
HasValueChangeHandlers<Boolean> getNoVncImplRadioButton();
HasValueChangeHandlers<Boolean> getVncNativeImplRadioButton();
HasValueChangeHandlers<Boolean> getRdpAutoImplRadioButton();
HasValueChangeHandlers<Boolean> getRdpNativeImplRadioButton();
HasValueChangeHandlers<Boolean> getRdpPluginImplRadioButton();
HasValueChangeHandlers<Boolean> getSpiceProxyEnabledCheckBox();
HasEnabledWithHints getEnableUsbAutoshare();
HasClickHandlers getConsoleClientResourcesAnchor();
void showRdpPanel(boolean visible);
void showSpicePanel(boolean visible);
void showVncPanel(boolean visible);
void selectSpice(boolean selected);
void selectRdp(boolean selected);
void selectVnc(boolean selected);
void setNoVncEnabled(boolean enabled, String reason);
void setAdditionalConsoleAvailable(boolean hasAdditionalConsole);
void setSpiceConsoleAvailable(boolean available);
void selectSpiceImplementation(SpiceConsoleModel.ClientConsoleMode consoleMode);
void setSpiceHtml5ImplEnabled(boolean enabled, String reason);
void setRdpPluginImplEnabled(boolean enabled, String reason);
void selectWanOptionsEnabled(boolean selected);
void setWanOptionsVisible(boolean visible);
void setDisableSmartcardVisible(boolean visible);
void setSpiceProxyEnabled(boolean enabled, String reason);
void setSpiceProxy(boolean enabled);
Boolean getSpiceProxy();
void selectVncImplementation(VncConsoleModel.ClientConsoleMode clientConsoleMode);
void selectRdpImplementation(RdpConsoleModel.ClientConsoleMode consoleMode);
void setVmName(String name);
void flushToPrivateModel();
void setCtrlAltDeleteRemapHotkey(String hotkey);
}
private final ConsoleUtils consoleUtils;
private IEventListener<EventArgs> viewUpdatingListener;
private boolean wanOptionsAvailable = false;
private ConsolePopupModel model;
private final DynamicMessages dynamicMessages;
private final ConsoleOptionsFrontendPersister consoleOptionsPersister;
private boolean spiceProxyUserPreference;
private boolean spiceProxyDefinedOnCluster;
private static final CommonApplicationConstants constants = AssetProvider.getConstants();
@Inject
public ConsolePopupPresenterWidget(EventBus eventBus, ViewDef view,
ConsoleUtils consoleUtils,
final DynamicMessages dynamicMessages,
ConsoleOptionsFrontendPersister consoleOptionsPersister) {
super(eventBus, view);
this.consoleUtils = consoleUtils;
this.consoleOptionsPersister = consoleOptionsPersister;
this.dynamicMessages = dynamicMessages;
}
@Override
public void init(final ConsolePopupModel model) {
this.model = model;
initView(model);
initListeners(model);
String vmName = (model.getVmConsoles() instanceof VmConsolesImpl)
? model.getVmConsoles().getVm().getName()
: model.getVmConsoles().getVm().getVmPoolName(); // for pool dialogs display pool name
getView().setVmName(vmName);
getView().setCtrlAltDeleteRemapHotkey(ConsoleOptions.SECURE_ATTENTION_MAPPING);
super.init(model);
}
private void initListeners(final ConsolePopupModel model) {
ConsoleClient spice = model.getVmConsoles().getConsoleModel(SpiceConsoleModel.class).getSpiceImpl();
if (spice == null) {
return;
}
viewUpdatingListener = (ev, sender, args) -> getView().edit(model);
}
private void removeListeners(ConsolePopupModel model) {
if (viewUpdatingListener == null) {
return;
}
ConsoleClient spice = model.getVmConsoles().getConsoleModel(SpiceConsoleModel.class).getSpiceImpl();
if (spice == null) {
return;
}
}
private void initView(ConsolePopupModel model) {
listenOnRadioButtons(model);
VmConsoles vmConsoles = model.getVmConsoles();
getView().setSpiceAvailable(vmConsoles.canSelectProtocol(ConsoleProtocol.SPICE));
getView().setVncAvailable(vmConsoles.canSelectProtocol(ConsoleProtocol.VNC));
getView().setRdpAvailable(vmConsoles.canSelectProtocol(ConsoleProtocol.RDP));
ConsoleProtocol selectedProtocol = vmConsoles.getSelectedProcotol();
boolean rdpPreselected = ConsoleProtocol.RDP.equals(selectedProtocol);
boolean spicePreselected = ConsoleProtocol.SPICE.equals(selectedProtocol);
boolean vncPreselected = ConsoleProtocol.VNC.equals(selectedProtocol);
getView().selectSpice(spicePreselected);
getView().selectRdp(rdpPreselected);
getView().selectVnc(vncPreselected);
getView().showSpicePanel(spicePreselected);
getView().showRdpPanel(rdpPreselected);
getView().showVncPanel(vncPreselected);
getView().setDisableSmartcardVisible(model.getVmConsoles().getVm().isSmartcardEnabled());
ConsoleClient spice = model.getVmConsoles().getConsoleModel(SpiceConsoleModel.class).getSpiceImpl();
if (spice != null) {
if (!spice.getOptions().isWanOptionsEnabled()) {
getView().selectWanOptionsEnabled(false);
}
spiceProxyUserPreference = vmConsoles.getConsoleModel(SpiceConsoleModel.class).getSpiceImpl().getOptions().isSpiceProxyEnabled();
}
getView().setSpiceHtml5ImplEnabled(consoleUtils.webBasedClientsSupported(), constants.webBasedClientsUnsupported());
getView().setNoVncEnabled(consoleUtils.webBasedClientsSupported(), constants.webBasedClientsUnsupported());
if (!consoleUtils.isBrowserPluginSupported(ConsoleProtocol.RDP)) {
getView().setRdpPluginImplEnabled(false, constants.rdpPluginNotSupportedByBrowser());
}
spiceProxyDefinedOnCluster = consoleUtils.isSpiceProxyDefined(vmConsoles.getVm());
selectSpiceImplementation(vmConsoles.getConsoleModel(SpiceConsoleModel.class).getClientConsoleMode());
getView().selectVncImplementation(vmConsoles.getConsoleModel(VncConsoleModel.class).getClientConsoleMode());
getView().selectRdpImplementation(vmConsoles.getConsoleModel(RdpConsoleModel.class).getClientConsoleMode());
wanOptionsAvailable = vmConsoles.getConsoleModel(SpiceConsoleModel.class).isWanOptionsAvailableForMyVm();
if (wanOptionsAvailable) {
getView().setWanOptionsVisible(true);
} else {
getView().setWanOptionsVisible(false);
}
getView().setAdditionalConsoleAvailable(vmConsoles.canSelectProtocol(ConsoleProtocol.RDP));
getView().setSpiceConsoleAvailable(vmConsoles.canSelectProtocol(ConsoleProtocol.SPICE));
registerHandler(getView().getConsoleClientResourcesAnchor().addClickHandler(event -> {
Window.open(dynamicMessages.consoleClientResourcesUrl(), "_blank", "resizable=yes,scrollbars=yes"); //$NON-NLS-1$ $NON-NLS-2$
}));
registerHandler(getView().getSpiceProxyEnabledCheckBox().addValueChangeHandler(
booleanValueChangeEvent -> spiceProxyUserPreference = booleanValueChangeEvent.getValue()
));
final boolean enableUsbAutoshareEnabled =
model.getVmConsoles().getVm().getUsbPolicy() == UsbPolicy.ENABLED_NATIVE;
if (enableUsbAutoshareEnabled) {
getView().getEnableUsbAutoshare().setEnabled(true);
} else {
getView().getEnableUsbAutoshare().disable(constants.enableUsbSupportNotAvailable());
}
}
@Override
protected void beforeCommandExecuted(UICommand command) {
super.beforeCommandExecuted(command);
if (command == model.getDefaultCommand()) {
// remove listeners which listens to changes in model before flushing
// data into it
removeListeners(model);
// now flush the model
getView().flushToPrivateModel();
// store to local storage
consoleOptionsPersister.storeToLocalStorage(model.getVmConsoles());
ConsoleModelChangedEvent.fire(this);
}
}
protected void listenOnRadioButtons(final ConsolePopupModel model) {
registerHandler(getView().getRdpRadioButton().addValueChangeHandler(event -> getView().showRdpPanel(event.getValue())));
registerHandler(getView().getVncRadioButton().addValueChangeHandler(event -> getView().showVncPanel(event.getValue())));
registerHandler(getView().getSpiceRadioButton().addValueChangeHandler(event -> getView().showSpicePanel(event.getValue())));
registerHandler(getView().getSpiceAutoImplRadioButton()
.addValueChangeHandler(event -> selectSpiceImplementation(SpiceConsoleModel.ClientConsoleMode.Auto)));
registerHandler(getView().getSpiceNativeImplRadioButton()
.addValueChangeHandler(event -> selectSpiceImplementation(SpiceConsoleModel.ClientConsoleMode.Native)));
registerHandler(getView().getSpiceHtml5ImplRadioButton()
.addValueChangeHandler(event -> {
boolean previousSpicePreference = getView().getSpiceProxy();
selectSpiceImplementation(SpiceConsoleModel.ClientConsoleMode.Html5);
spiceProxyUserPreference = previousSpicePreference;
}));
registerHandler(getView().getNoVncImplRadioButton()
.addValueChangeHandler(event -> getView().selectVncImplementation(VncConsoleModel.ClientConsoleMode.NoVnc)));
registerHandler(getView().getVncNativeImplRadioButton()
.addValueChangeHandler(event -> getView().selectVncImplementation(VncConsoleModel.ClientConsoleMode.Native)));
registerHandler(getView().getRdpAutoImplRadioButton()
.addValueChangeHandler(event -> getView().selectRdpImplementation(RdpConsoleModel.ClientConsoleMode.Auto)));
registerHandler(getView().getRdpNativeImplRadioButton()
.addValueChangeHandler(event -> getView().selectRdpImplementation(RdpConsoleModel.ClientConsoleMode.Native)));
registerHandler(getView().getRdpPluginImplRadioButton()
.addValueChangeHandler(event -> getView().selectRdpImplementation(RdpConsoleModel.ClientConsoleMode.Plugin)));
}
/**
* Selects spice implementation.
* Handles spice proxy availability as well.
*/
private void selectSpiceImplementation(SpiceConsoleModel.ClientConsoleMode clientMode) {
getView().selectSpiceImplementation(clientMode);
setSpiceProxyAvailability(clientMode);
getView().setSpiceProxy(clientMode == SpiceConsoleModel.ClientConsoleMode.Html5
? false
: spiceProxyUserPreference);
}
private void setSpiceProxyAvailability(SpiceConsoleModel.ClientConsoleMode clientMode) {
boolean isHtml5 = clientMode == SpiceConsoleModel.ClientConsoleMode.Html5;
// firstly handle availability on cluster
getView().setSpiceProxyEnabled(
spiceProxyDefinedOnCluster,
spiceProxyDefinedOnCluster ? "" : constants.spiceProxyCanBeEnabledOnlyWhenDefined()); //$NON-NLS-1$
// then, if it's available on cluster, check if it's supported by selected client
if (spiceProxyDefinedOnCluster) {
getView().setSpiceProxyEnabled(
!isHtml5,
isHtml5 ? constants.spiceHtml5DoesntSupportSpiceProxy() : ""); //$NON-NLS-1$
}
}
}