org.chromium.debug.ui.launcher.ChromiumRemoteTab.java Source code

Java tutorial

Introduction

Here is the source code for org.chromium.debug.ui.launcher.ChromiumRemoteTab.java

Source

// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.debug.ui.launcher;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.chromium.debug.core.ChromiumDebugPlugin;
import org.chromium.debug.core.ChromiumSourceDirector;
import org.chromium.debug.core.SourceNameMapperContainer;
import org.chromium.debug.core.model.BreakpointSynchronizer.Direction;
import org.chromium.debug.core.model.LaunchParams;
import org.chromium.debug.core.model.LaunchParams.LookupMode;
import org.chromium.debug.core.model.LaunchParams.ValueConverter;
import org.chromium.debug.ui.launcher.LaunchTabGroup.Params;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.core.sourcelookup.IPersistableSourceLocator2;
import org.eclipse.debug.core.sourcelookup.ISourceContainer;
import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
import org.eclipse.debug.internal.ui.SWTFactory;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.preference.IntegerFieldEditor;
import org.eclipse.jface.preference.PreferenceStore;
import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;

/**
 * The "Remote" tab for the Chromium JavaScript launch tab group.
 * @param <ELEMENTS> type used for access to created dialog elements; it is used internally
 *     and allows to subclass {@link ChromiumRemoteTab} with additional dialog controls
 */
public abstract class ChromiumRemoteTab<ELEMENTS> extends TabBase<ELEMENTS, Params> {
    private static final String HOST_FIELD_NAME = "host_field"; //$NON-NLS-1$
    private static final String PORT_FIELD_NAME = "port_field"; //$NON-NLS-1$
    private static final String ADD_NETWORK_CONSOLE_FIELD_NAME = "add_network_console_field"; //$NON-NLS-1$

    // However, recommended range is [1024, 32767].
    private static final int minimumPortValue = 0;
    private static final int maximumPortValue = 65535;

    private final SourceContainerChecker sourceContainerChecker = new SourceContainerChecker();

    /**
     * Possibly checks host property in config.
     */
    public static abstract class HostChecker {
        public abstract String getWarning(ILaunchConfiguration config) throws CoreException;

        public static HostChecker LOCAL_ONLY = new HostChecker() {
            @Override
            public String getWarning(ILaunchConfiguration config) throws CoreException {
                String host = config.getAttribute(LaunchParams.CHROMIUM_DEBUG_HOST, ""); //$NON-NLS-1$
                if (!LOCAL_HOST_NAMES.contains(host.toLowerCase())) {
                    return Messages.ChromiumRemoteTab_CONNECTION_FROM_LOCALHOST_WARNING;
                }
                return null;
            }
        };

        private static final Collection<String> LOCAL_HOST_NAMES = Arrays.asList("localhost", "127.0.0.1"); //$NON-NLS-1$ //$NON-NLS-2$
    }

    ChromiumRemoteTab(Params params) {
        super(params);
    }

    @Override
    protected ELEMENTS createElements(Composite parent, Runnable modifyListener) {
        Composite composite = createDefaultComposite(parent);
        setControl(composite);

        PreferenceStore store = new PreferenceStore();

        composite.setFont(parent.getFont());

        return createDialogElements(composite, modifyListener, store);
    }

    protected abstract ELEMENTS createDialogElements(Composite composite, Runnable modifyListener,
            PreferenceStore store);

    protected static TabElements createBasicTabElements(Composite composite, final Runnable modifyListener,
            PreferenceStore store, Params params) {
        final StringFieldEditor debugHost;
        final IntegerFieldEditor debugPort;
        final BooleanFieldEditor addNetworkConsole;
        {
            Group connectionGroup = new Group(composite, 0);
            connectionGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
            connectionGroup.setText(Messages.ChromiumRemoteTab_CONNECTION_GROUP);
            connectionGroup.setLayout(new GridLayout(1, false));

            IPropertyChangeListener propertyModifyListener = new IPropertyChangeListener() {
                public void propertyChange(PropertyChangeEvent event) {
                    modifyListener.run();
                }
            };

            Composite propertiesComp = createInnerComposite(connectionGroup, 2);

            // Host text field
            debugHost = new StringFieldEditor(HOST_FIELD_NAME, Messages.ChromiumRemoteTab_HostLabel,
                    propertiesComp);
            debugHost.setPropertyChangeListener(propertyModifyListener);
            debugHost.setPreferenceStore(store);

            // Port text field
            debugPort = new IntegerFieldEditor(PORT_FIELD_NAME, Messages.ChromiumRemoteTab_PortLabel,
                    propertiesComp);
            debugPort.setPropertyChangeListener(propertyModifyListener);
            debugPort.setPreferenceStore(store);

            addNetworkConsole = new BooleanFieldEditor(ADD_NETWORK_CONSOLE_FIELD_NAME,
                    Messages.ChromiumRemoteTab_ShowDebuggerNetworkCommunication, propertiesComp);
            addNetworkConsole.setPreferenceStore(store);
            addNetworkConsole.setPropertyChangeListener(propertyModifyListener);
        }

        return new TabElements() {
            @Override
            public StringFieldEditor getHost() {
                return debugHost;
            }

            @Override
            public IntegerFieldEditor getPort() {
                return debugPort;
            }

            @Override
            public BooleanFieldEditor getAddNetworkConsole() {
                return addNetworkConsole;
            }
        };
    }

    public String getName() {
        return Messages.ChromiumRemoteTab_RemoteTabName;
    }

    @Override
    protected MessageData isValidImpl(ILaunchConfiguration config) throws CoreException {
        int port = config.getAttribute(LaunchParams.CHROMIUM_DEBUG_PORT, -1);
        if (port < minimumPortValue || port > maximumPortValue) {
            return new MessageData(false, Messages.ChromiumRemoteTab_InvalidPortNumberError);
        }
        String message = getWarning(config);
        return new MessageData(true, message);
    }

    /**
     * Checks config for warnings and returns first found or null.
     */
    protected String getWarning(ILaunchConfiguration config) throws CoreException {
        HostChecker hostChecker = getParams().getHostChecker();
        if (hostChecker != null) {
            String hostWarning = hostChecker.getWarning(config);
            if (hostWarning != null) {
                return hostWarning;
            }
        }
        return sourceContainerChecker.check(config);
    }

    @Override
    public Image getImage() {
        return DebugUITools.getImage(IDebugUIConstants.IMG_LCL_DISCONNECT);
    }

    interface TabElements {
        StringFieldEditor getHost();

        IntegerFieldEditor getPort();

        BooleanFieldEditor getAddNetworkConsole();
    }

    static final TabFieldList<TabElements, Params> BASIC_TAB_FIELDS;
    static {
        List<TabField<?, ?, ? super TabElements, Params>> list = new ArrayList<ChromiumRemoteTab.TabField<?, ?, ? super TabElements, Params>>(
                4);

        list.add(new TabField<String, String, TabElements, Params>(LaunchParams.CHROMIUM_DEBUG_HOST,
                TypedMethods.STRING, new FieldEditorAccess<String, TabElements>(TypedMethods.STRING) {
                    @Override
                    FieldEditor getFieldEditor(TabElements tabElements) {
                        return tabElements.getHost();
                    }

                    String getEditorErrorValue() {
                        return ""; //$NON-NLS-1$
                    }
                }, new DefaultsProvider<String, Params>() {
                    @Override
                    String getFallbackValue() {
                        return PluginVariablesUtil.getValue(PluginVariablesUtil.DEFAULT_HOST);
                    }

                    @Override
                    String getInitialConfigValue(Params context) {
                        return getFallbackValue();
                    }
                }, ValueConverter.<String>getTrivial()));

        list.add(new TabField<Integer, Integer, TabElements, Params>(LaunchParams.CHROMIUM_DEBUG_PORT,
                TypedMethods.INT, new FieldEditorAccess<Integer, TabElements>(TypedMethods.INT) {
                    @Override
                    FieldEditor getFieldEditor(TabElements tabElements) {
                        return tabElements.getPort();
                    }

                    String getEditorErrorValue() {
                        return "-1"; //$NON-NLS-1$
                    }
                }, new DefaultsProvider<Integer, Params>() {
                    @Override
                    Integer getFallbackValue() {
                        return PluginVariablesUtil.getValueAsInt(PluginVariablesUtil.DEFAULT_PORT);
                    }

                    @Override
                    Integer getInitialConfigValue(Params context) {
                        return getFallbackValue();
                    }
                }, ValueConverter.<Integer>getTrivial()));

        list.add(new TabField<Boolean, Boolean, TabElements, Params>(LaunchParams.ADD_NETWORK_CONSOLE,
                TypedMethods.BOOL, new FieldEditorAccess<Boolean, TabElements>(TypedMethods.BOOL) {
                    FieldEditor getFieldEditor(TabElements tabElements) {
                        return tabElements.getAddNetworkConsole();
                    }

                    String getEditorErrorValue() {
                        return ""; //$NON-NLS-1$
                    }
                }, new DefaultsProvider<Boolean, Params>() {
                    @Override
                    Boolean getFallbackValue() {
                        return false;
                    }

                    @Override
                    Boolean getInitialConfigValue(Params context) {
                        return null;
                    }
                }, ValueConverter.<Boolean>getTrivial()));

        BASIC_TAB_FIELDS = createFieldListImpl(list);
    }

    private static class SourceContainerChecker {
        public String check(ILaunchConfiguration config) {
            LookupMode lookupMode;
            try {
                lookupMode = ChromiumSourceDirector.readLookupMode(config);
            } catch (CoreException e) {
                ChromiumDebugPlugin.log(e);
                return null;
            }
            if (lookupMode != LookupMode.AUTO_DETECT) {
                return null;
            }

            ISourceLookupDirector director;
            try {
                director = read(config);
            } catch (CoreException e) {
                return null;
            }
            if (director == null) {
                return null;
            }
            for (ISourceContainer sourceContainer : director.getSourceContainers()) {
                if (sourceContainer instanceof SourceNameMapperContainer) {
                    return Messages.ChromiumRemoteTab_AUTO_DETECT_CONTAINER_WARNING;
                }
            }
            return null;
        }

        private ISourceLookupDirector read(ILaunchConfiguration config) throws CoreException {
            String memento = config.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String) null);
            if (memento == null) {
                return null;
            }
            String type = config.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, (String) null);
            if (type == null) {
                type = config.getType().getSourceLocatorId();
            }
            ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
            ISourceLocator locator = launchManager.newSourceLocator(type);
            if (locator instanceof IPersistableSourceLocator2 == false) {
                return null;
            }
            ISourceLookupDirector director = (ISourceLookupDirector) locator;
            director.initializeFromMemento(memento, config);
            return director;
        }
    }

    static abstract class DevToolsProtocolBase extends ChromiumRemoteTab<DevToolsElements> {
        DevToolsProtocolBase(Params params) {
            super(params);
        }

        @Override
        protected DevToolsElements createDialogElements(Composite composite, final Runnable modifyListener,
                PreferenceStore store) {
            final TabElements basicElements = createBasicTabElements(composite, modifyListener, store, getParams());

            RadioButtonsLogic.Listener radioButtonsListener = new RadioButtonsLogic.Listener() {
                public void selectionChanged() {
                    modifyListener.run();
                }
            };

            final RadioButtonsLogic<Integer> breakpointRadioButtons;
            {
                Group breakpointGroup = new Group(composite, 0);
                breakpointGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
                breakpointGroup.setText(Messages.ChromiumRemoteTab_BREAKPOINT_GROUP);
                breakpointGroup.setLayout(new GridLayout(1, false));

                Map<Integer, Button> buttonMap = new LinkedHashMap<Integer, Button>(3);
                for (LaunchParams.BreakpointOption option : LaunchParams.BREAKPOINT_OPTIONS) {
                    Button button = new Button(breakpointGroup, SWT.RADIO);
                    button.setFont(composite.getFont());
                    button.setText(option.getLabel());
                    GridData gd = new GridData();
                    button.setLayoutData(gd);
                    SWTFactory.setButtonDimensionHint(button);
                    int index = buttonMap.size();
                    buttonMap.put(index, button);
                }

                breakpointRadioButtons = new RadioButtonsLogic<Integer>(buttonMap, radioButtonsListener);
            }

            return new DevToolsElements() {
                @Override
                public RadioButtonsLogic<Integer> getBreakpointRadioButtons() {
                    return breakpointRadioButtons;
                }

                @Override
                public TabElements getBase() {
                    return basicElements;
                }
            };
        }

        @Override
        protected TabFieldList<? super DevToolsElements, ? super Params> getTabFields() {
            return TAB_FIELD_LIST;
        }

        private static final TabFieldList<? super DevToolsElements, ? super Params> TAB_FIELD_LIST;
        static {
            TabField<String, String, DevToolsElements, Params> breakpointSyncField = new TabField<String, String, DevToolsElements, Params>(
                    LaunchParams.BREAKPOINT_SYNC_DIRECTION, TypedMethods.STRING,
                    new FieldAccess<String, DevToolsElements>() {
                        @Override
                        void setValue(String value, DevToolsElements tabElements) {
                            int breakpointOptionIndex = LaunchParams.findBreakpointOption(value);
                            tabElements.getBreakpointRadioButtons().select(breakpointOptionIndex);
                        }

                        @Override
                        String getValue(DevToolsElements tabElements) {
                            int breakpointOption = tabElements.getBreakpointRadioButtons().getSelected();
                            return LaunchParams.BREAKPOINT_OPTIONS.get(breakpointOption).getDirectionStringValue();
                        }
                    }, new DefaultsProvider<String, Params>() {
                        @Override
                        String getFallbackValue() {
                            return Direction.MERGE.toString();
                        }

                        @Override
                        String getInitialConfigValue(Params context) {
                            return null;
                        }
                    }, ValueConverter.<String>getTrivial());

            List<TabFieldList<? super DevToolsElements, ? super Params>> subLists = new ArrayList<TabBase.TabFieldList<? super DevToolsElements, ? super Params>>(
                    2);
            subLists.add(createFieldListAdapting(BASIC_TAB_FIELDS, new Adapter<DevToolsElements, TabElements>() {
                @Override
                public TabElements get(DevToolsElements from) {
                    return from.getBase();
                }
            }));
            subLists.add(createFieldListImpl(Collections.singletonList(breakpointSyncField)));

            TAB_FIELD_LIST = createCompositeFieldList(subLists);
        }
    }

    interface DevToolsElements {
        RadioButtonsLogic<Integer> getBreakpointRadioButtons();

        TabElements getBase();
    }

    static class DevToolsProtocol extends DevToolsProtocolBase {
        public DevToolsProtocol() {
            super(PARAMS);
        }

        private static final Params PARAMS = new Params(ChromiumRemoteTab.HostChecker.LOCAL_ONLY,
                Messages.ChromiumRemoteTab_URL, false);
    }

    static class Standalone extends DevToolsProtocolBase {
        public Standalone() {
            super(PARAMS);
        }

        private static final Params PARAMS = new Params(null, Messages.ChromiumRemoteTab_FILE_PATH, true);
    }
}