blob: ca6726926d6f8c7917c9f550e7f5ba52e3bf9972 [file] [log] [blame]
package com.intellij.ide.browsers;
import com.google.common.net.HostAndPort;
import com.intellij.concurrency.JobScheduler;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Urls;
import com.intellij.util.net.NetUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.net.URI;
import java.util.concurrent.TimeUnit;
/**
* @author Sergey Simonchik
*/
public class BrowserStarter {
private static final Logger LOG = Logger.getInstance(BrowserStarter.class);
private final StartBrowserSettings mySettings;
private final RunConfiguration myRunConfiguration;
private final ProcessHandler myServerProcessHandler;
public BrowserStarter(@NotNull RunConfiguration runConfiguration, @NotNull StartBrowserSettings settings, @NotNull ProcessHandler serverProcessHandler) {
mySettings = settings;
myRunConfiguration = runConfiguration;
myServerProcessHandler = serverProcessHandler;
}
public void start() {
if (!mySettings.isSelected() || mySettings.getUrl() == null) {
return;
}
HostAndPort hostAndPort = getHostAndPort(mySettings.getUrl());
if (hostAndPort != null) {
checkAndOpenPageLater(hostAndPort, 1, 300);
}
else {
// we can't check page availability gracefully, so we just open it after some delay
openPageLater(1000);
}
}
@Nullable
private static HostAndPort getHostAndPort(@NotNull String rawUrl) {
URI url = Urls.parseAsJavaUriWithoutParameters(rawUrl);
if (url == null) {
return null;
}
int port = url.getPort();
if (port == -1) {
port = "https".equals(url.getScheme()) ? 443 : 80;
}
return HostAndPort.fromParts(StringUtil.notNullize(url.getHost(), "127.0.0.1"), port);
}
private void checkAndOpenPageLater(@NotNull final HostAndPort hostAndPort, final int attemptNumber, int delayMillis) {
JobScheduler.getScheduler().schedule(new Runnable() {
@Override
public void run() {
checkAndOpenPage(hostAndPort, attemptNumber);
}
}, delayMillis, TimeUnit.MILLISECONDS);
}
private void checkAndOpenPage(@NotNull final HostAndPort hostAndPort, final int attemptNumber) {
if (NetUtils.canConnectToRemoteSocket(hostAndPort.getHostText(), hostAndPort.getPort())) {
openPageNow();
}
else {
LOG.info("[attempt#" + attemptNumber + "] Checking " + hostAndPort + " failed");
if (!isProcessTerminated()) {
int delayMillis = getDelayMillis(attemptNumber);
checkAndOpenPageLater(hostAndPort, attemptNumber + 1, delayMillis);
}
}
}
private static int getDelayMillis(int attemptNumber) {
if (attemptNumber < 10) {
return 400;
}
if (attemptNumber < 100) {
return 1000;
}
return 2000;
}
private void openPageLater(int millis) {
JobScheduler.getScheduler().schedule(new Runnable() {
@Override
public void run() {
openPageNow();
}
}, millis, TimeUnit.MILLISECONDS);
}
private void openPageNow() {
if (!isProcessTerminated()) {
JavaScriptDebuggerStarter.Util.startDebugOrLaunchBrowser(myRunConfiguration, mySettings);
}
}
private boolean isProcessTerminated() {
return myServerProcessHandler.isProcessTerminating() || myServerProcessHandler.isProcessTerminated();
}
}