package com.google.dart.tools.debug.ui.internal.dialogs; import com.google.dart.tools.core.DartCore; import com.google.dart.tools.core.mobile.AndroidDebugBridge; import com.google.dart.tools.core.mobile.AndroidDevice; import com.google.dart.tools.debug.ui.internal.mobile.MobileMainTab; import com.google.dart.tools.ui.internal.util.ExternalBrowserUtil; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Point; 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.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Shell; import java.net.ConnectException; public class MobilePortForwardDialog extends Dialog { private final String pageUrl; private Link descriptionLabel; private Label testResultLabel; public MobilePortForwardDialog(Shell parentShell, String pageUrl, boolean localhostOverUsb) { super(parentShell); this.pageUrl = pageUrl; setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE); } @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText("Mobile Launch"); } @Override protected Control createButtonBar(Composite parent) { Composite buttonBar = (Composite) super.createButtonBar(parent); ((GridLayout) buttonBar.getLayout()).makeColumnsEqualWidth = false; buttonBar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER)); return buttonBar; } @Override protected void createButtonsForButtonBar(Composite parent) { final Button testButton = createButton( parent, IDialogConstants.CLIENT_ID, "Test Connection", false); testButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } @Override public void widgetSelected(SelectionEvent e) { testConnection(); } }); testButton.getDisplay().asyncExec(new Runnable() { @Override public void run() { testButton.setFocus(); } }); // increment the number of columns in the button bar ((GridLayout) parent.getLayout()).numColumns++; testResultLabel = new Label(parent, SWT.NONE); testResultLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); Button closeButton = createButton( parent, IDialogConstants.CLOSE_ID, IDialogConstants.CLOSE_LABEL, true); closeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } @Override public void widgetSelected(SelectionEvent e) { close(); } }); } @Override protected Control createDialogArea(Composite parent) { Composite container = (Composite) super.createDialogArea(parent); container.setLayout(new GridLayout(2, false)); descriptionLabel = new Link(container, SWT.WRAP); GridData gd_descriptionLabel = new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1); gd_descriptionLabel.verticalIndent = 20; gd_descriptionLabel.horizontalIndent = 20; descriptionLabel.setLayoutData(gd_descriptionLabel); descriptionLabel.setText("Unable to access the web server" + " on the developer machine from the mobile device.\n\n" + "Looks like port forwarding has not been setup between device and the machine.\n" + "Follow the steps listed under " // + " <a href=\"" + MobileMainTab.PORT_FORWARD_DOC_URL + "\">Set up port forwarding</a>\n" + "\n\nOnce you are done, use Test Connection to verify the setup."); descriptionLabel.addSelectionListener(new SelectionListener() { @Override public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } @Override public void widgetSelected(SelectionEvent e) { ExternalBrowserUtil.openInExternalBrowser(e.text.trim()); } }); return container; } /** * Return the initial size of the dialog. */ @Override protected Point getInitialSize() { return getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT); } /** * Test the connection between the mobile device and the webserver on the development machine. */ private void testConnection() { testResultLabel.setText("Testing connection..."); // Test connection on a background thread Thread thread = new Thread("Test Mobile Port Forwarding") { @Override public void run() { long startTime = System.currentTimeMillis(); // Test connection from mobile device to developer machine final IStatus status = testConnectionInBackground(); // Ensure text is visible for at least 1 1/2 seconds long delta = startTime + 1500 - System.currentTimeMillis(); if (delta > 0) { try { Thread.sleep(delta); } catch (InterruptedException e) { //$FALL-THROUGH$ } } getShell().getDisplay().asyncExec(new Runnable() { @Override public void run() { String message; if (status.isOK()) { message = "Connection validated"; } else { message = status.getMessage(); } if (message.startsWith(ConnectException.class.getName())) { message = message.substring(ConnectException.class.getName().length() + 2).trim(); } testResultLabel.setText(message); } }); } }; thread.setDaemon(true); thread.start(); } private IStatus testConnectionInBackground() { AndroidDebugBridge debugBridge = AndroidDebugBridge.getAndroidDebugBridge(); // Check that the device is still connected and authorized AndroidDevice device = debugBridge.getConnectedDevice(); if (device == null) { return new Status(IStatus.ERROR, DartCore.PLUGIN_ID, "No device connected"); } if (!device.isAuthorized()) { return new Status(IStatus.ERROR, DartCore.PLUGIN_ID, "Connected device is not authorized"); } return debugBridge.isHtmlPageAccessible(device, pageUrl); } }