package com.intellij.javascript.karma.debug; import com.google.common.collect.ImmutableList; import com.intellij.execution.filters.HyperlinkInfo; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ExecutionUtil; import com.intellij.execution.ui.ConsoleView; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.ide.browsers.WebBrowser; import com.intellij.ide.browsers.WebBrowserManager; import com.intellij.javascript.karma.execution.KarmaRunConfiguration; import com.intellij.javascript.karma.server.CapturedBrowser; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ObjectUtils; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.List; public class KarmaDebugBrowserSelector { private static final Key<WebBrowser> WEB_BROWSER_KEY = Key.create("KARMA_WEB_BROWSER_ID"); private final ImmutableList<CapturedBrowser> myCapturedBrowsers; private final ExecutionEnvironment myEnvironment; private final ConsoleView myConsoleView; protected KarmaDebugBrowserSelector(@NotNull Collection<CapturedBrowser> browsers, @NotNull ExecutionEnvironment environment, @NotNull ConsoleView consoleView) { myCapturedBrowsers = ImmutableList.copyOf(browsers); myEnvironment = environment; myConsoleView = consoleView; } @Nullable public DebuggableWebBrowser selectDebugEngine() { List<DebuggableWebBrowser> allDebuggableActiveBrowsers = toDebuggableWebBrowsers(WebBrowserManager.getInstance().getActiveBrowsers()); List<DebuggableWebBrowser> capturedDebuggableActiveBrowsers = filterCaptured(allDebuggableActiveBrowsers); if (capturedDebuggableActiveBrowsers.size() == 1) { DebuggableWebBrowser debuggableWebBrowser = capturedDebuggableActiveBrowsers.get(0); setWebBrowserToReuse(null); return ObjectUtils.assertNotNull(debuggableWebBrowser); } WebBrowser browserToReuse = getWebBrowserToReuse(); if (browserToReuse != null) { DebuggableWebBrowser debuggableBrowser = DebuggableWebBrowser.create(browserToReuse); if (debuggableBrowser != null) { return debuggableBrowser; } } if (capturedDebuggableActiveBrowsers.isEmpty() && allDebuggableActiveBrowsers.size() == 1) { return ObjectUtils.assertNotNull(allDebuggableActiveBrowsers.get(0)); } printSupportedBrowsers(allDebuggableActiveBrowsers, capturedDebuggableActiveBrowsers); return null; } @NotNull private static List<DebuggableWebBrowser> toDebuggableWebBrowsers(@NotNull List<WebBrowser> browsers) { List<DebuggableWebBrowser> debuggableWebBrowsers = new SmartList<>(); for (WebBrowser browser : browsers) { DebuggableWebBrowser debuggableBrowser = DebuggableWebBrowser.create(browser); if (debuggableBrowser != null) { debuggableWebBrowsers.add(debuggableBrowser); } } return ImmutableList.copyOf(debuggableWebBrowsers); } @NotNull private List<DebuggableWebBrowser> filterCaptured(@NotNull List<DebuggableWebBrowser> debuggableBrowsers) { List<DebuggableWebBrowser> captured = ContainerUtil.filter(debuggableBrowsers, debuggableBrowser -> { String browserName = debuggableBrowser.getWebBrowser().getName(); for (CapturedBrowser capturedBrowser : myCapturedBrowsers) { if (StringUtil.containsIgnoreCase(capturedBrowser.getName(), browserName)) { return true; } } return false; }); return ImmutableList.copyOf(captured); } @Nullable private WebBrowser getWebBrowserToReuse() { KarmaRunConfiguration runConfiguration = ObjectUtils.tryCast(myEnvironment.getRunProfile(), KarmaRunConfiguration.class); if (runConfiguration != null) { WebBrowser browser = WEB_BROWSER_KEY.get(runConfiguration); // browser can be removed or deactivated in "Settings | Web Browsers" if (!WebBrowserManager.getInstance().getActiveBrowsers().contains(browser)) { WEB_BROWSER_KEY.set(runConfiguration, null); return null; } return browser; } return null; } private void setWebBrowserToReuse(@Nullable WebBrowser browser) { KarmaRunConfiguration runConfiguration = ObjectUtils.tryCast(myEnvironment.getRunProfile(), KarmaRunConfiguration.class); if (runConfiguration != null) { WEB_BROWSER_KEY.set(runConfiguration, browser); } } private void printSupportedBrowsers(@NotNull List<DebuggableWebBrowser> allDebuggableActiveBrowsers, @NotNull List<DebuggableWebBrowser> capturedDebuggableActiveBrowsers) { if (capturedDebuggableActiveBrowsers.isEmpty()) { if (allDebuggableActiveBrowsers.isEmpty()) { myConsoleView.print("No supported browsers found.\n", ConsoleViewContentType.SYSTEM_OUTPUT); myConsoleView.print("JavaScript debugging is currently supported in Chrome or Firefox.\n", ConsoleViewContentType.SYSTEM_OUTPUT); } else { printVariants(allDebuggableActiveBrowsers); } } else { printVariants(capturedDebuggableActiveBrowsers); } } private void printVariants(@NotNull Collection<DebuggableWebBrowser> browsers) { myConsoleView.print("Debug karma tests in:\n", ConsoleViewContentType.SYSTEM_OUTPUT); for (DebuggableWebBrowser browser : browsers) { myConsoleView.print(" * ", ConsoleViewContentType.SYSTEM_OUTPUT); myConsoleView.printHyperlink(browser.getWebBrowser().getName(), new DebugHyperlinkInfo(browser.getWebBrowser())); myConsoleView.print("\n", ConsoleViewContentType.SYSTEM_OUTPUT); } } private class DebugHyperlinkInfo implements HyperlinkInfo { private final WebBrowser myWebBrowser; public DebugHyperlinkInfo(@NotNull WebBrowser webBrowser) { myWebBrowser = webBrowser; } @Override public void navigate(Project project) { setWebBrowserToReuse(myWebBrowser); ExecutionUtil.restart(myEnvironment); } } }