Skip to content

✨ Support multiple running instance for inspectors #6772

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 58 additions & 22 deletions flutter-idea/src/io/flutter/jxbrowser/EmbeddedBrowser.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@

import java.awt.*;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
Expand All @@ -50,7 +52,8 @@ public static EmbeddedBrowser getInstance(@NotNull Project project) {
return Objects.requireNonNull(project.getService(EmbeddedBrowser.class));
}

private Browser browser;
private final Map<@NotNull String, @NotNull Browser> browsers = new HashMap<>();
private final Map<@NotNull String, @NotNull Content> contents = new HashMap<>();
private CompletableFuture<DevToolsUrl> devToolsUrlFuture;

private EmbeddedBrowser(Project project) {
Expand All @@ -61,18 +64,46 @@ private EmbeddedBrowser(Project project) {
System.setProperty("jxbrowser.logging.level", "ALL");
}

ProjectManager.getInstance().addProjectManagerListener(project, new ProjectManagerListener() {
@Override
public void projectClosing(@NotNull Project project) {
for (final String key: browsers.keySet()) {
final Browser browser = browsers.get(key);
if (browser != null) {
try {
browser.close();
} catch (Exception ex) {
LOG.info(ex);
}
browsers.remove(key);
}
}
contents.clear();
}
});
}

private void openBrowserInstanceFor(String tabName) {
try {
final Engine engine = EmbeddedBrowserEngine.getInstance().getEngine();
if (engine == null) {
return;
}

this.browser = engine.newBrowser();
browser.settings().enableTransparentBackground();
browser.on(ConsoleMessageReceived.class, event -> {
final Browser newBrowser = engine.newBrowser();
newBrowser.settings().enableTransparentBackground();
newBrowser.on(ConsoleMessageReceived.class, event -> {
final ConsoleMessage consoleMessage = event.consoleMessage();
LOG.info("Browser message(" + consoleMessage.level().name() + "): " + consoleMessage.message());
});
final Browser oldBrowser = browsers.get(tabName);
if (oldBrowser != null) {
try {
oldBrowser.close();
} catch (Exception ex) {
LOG.info(ex);
}
}
browsers.put(tabName, newBrowser);
}
catch (UnsupportedRenderingModeException ex) {
// Skip using a transparent background if an exception is thrown.
Expand All @@ -81,22 +112,7 @@ private EmbeddedBrowser(Project project) {
LOG.info(ex);
FlutterInitializer.getAnalytics().sendExpectedException("jxbrowser-setup", ex);
}

resetUrl();

ProjectManager.getInstance().addProjectManagerListener(project, new ProjectManagerListener() {
@Override
public void projectClosing(@NotNull Project project) {
if (browser != null) {
try {
browser.close();
} catch (Exception ex) {
LOG.info(ex);
}
browser = null;
}
}
});
}

/**
Expand All @@ -109,8 +125,13 @@ public void resetUrl() {
this.devToolsUrlFuture = new CompletableFuture<>();
}

public void openPanel(ContentManager contentManager, String tabName, DevToolsUrl devToolsUrl, Runnable onBrowserUnavailable) {
public void openPanel(ContentManager contentManager, @NotNull String tabName, DevToolsUrl devToolsUrl, Runnable onBrowserUnavailable) {
final Browser firstBrowser = browsers.get(tabName);
if (browsers.get(tabName) == null) {
openBrowserInstanceFor(tabName);
}
// If the browser failed to start during setup, run unavailable callback.
final Browser browser = browsers.get(tabName);
if (browser == null) {
onBrowserUnavailable.run();
return;
Expand Down Expand Up @@ -141,6 +162,17 @@ public void openPanel(ContentManager contentManager, String tabName, DevToolsUrl
}

contentManager.removeAllContents(false);
if (contents.get(tabName) != null) {
contents.remove(tabName);
}
for (final Content content: contents.values()) {
contentManager.addContent(content);
}
final Content previousContent = contents.get(tabName);
if (previousContent != null) {
contentManager.setSelectedContent(previousContent, true);
return;
}
final Content content = contentManager.getFactory().createContent(null, tabName, false);

// Creating Swing component for rendering web content
Expand All @@ -158,6 +190,8 @@ public void openPanel(ContentManager contentManager, String tabName, DevToolsUrl
// TODO(helin24): Use differentiated icons for each tab and copy from devtools toolbar.
content.setIcon(FlutterIcons.Phone);
contentManager.addContent(content);
contentManager.setSelectedContent(content, true);
contents.put(tabName, content);

// This is for pulling up Chrome inspector for debugging purposes.
browser.set(PressKeyCallback.class, params -> {
Expand Down Expand Up @@ -227,7 +261,9 @@ private void updateUrlAndReload(Function<DevToolsUrl, DevToolsUrl> newDevToolsUr
// Reload is no longer needed - either URL has been reset or there has been no change.
return;
}
browser.navigation().loadUrl(devToolsUrl.getUrlString());
for (final Browser browser: browsers.values()) {
browser.navigation().loadUrl(devToolsUrl.getUrlString());
}
});
}
}
2 changes: 2 additions & 0 deletions flutter-idea/src/io/flutter/run/FlutterDevice.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ public String toString() {
/**
* Given a collection of devices, return a unique name for this device.
*/
@NotNull
public String getUniqueName(Collection<FlutterDevice> devices) {
for (final FlutterDevice other : devices) {
if (other == this) {
Expand Down Expand Up @@ -141,6 +142,7 @@ public static FlutterDevice getTester() {
return new FlutterDevice("flutter-tester", "Flutter test device", null, false);
}

@NotNull
public String presentationName() {
if (category() != null) {
return deviceName() + " (" + category() + ")";
Expand Down
1 change: 0 additions & 1 deletion flutter-idea/src/io/flutter/view/FlutterView.java
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,6 @@ private void replacePanelLabel(ToolWindow toolWindow, JComponent label) {
if (contentManager.isDisposed()) {
return;
}
contentManager.removeAllContents(true);

final JPanel panel = new JPanel(new BorderLayout());
panel.add(label, BorderLayout.CENTER);
Expand Down