java/com/jetbrains/cef/JCefAppConfig.java (223 lines of code) (raw):
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.jetbrains.cef;
import com.jetbrains.cef.remote.NativeServerManager;
import org.cef.CefApp;
import org.cef.CefSettings;
import org.cef.OS;
import org.cef.SystemBootstrap;
import org.cef.misc.Utils;
import java.awt.*;
import java.io.*;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author Anton Tarasov
* TODO: Why it's abstact? Check if removing abstract can be promoted
*/
public abstract class JCefAppConfig {
protected final CefSettings cefSettings = new CefSettings();
protected final List<String> appArgs = new ArrayList<>();
protected SystemBootstrap.Loader loader = null;
private String cefFrameworkPathOSX = null;
private static final AtomicReference<Double> forceDeviceScaleFactor = new AtomicReference<>(Double.valueOf(0));
private String nativeBundlePath = null;
public String[] getAppArgs() {
return appArgs.toArray(new String[0]);
}
public List<String> getAppArgsAsList() {
return appArgs;
}
public CefSettings getCefSettings() {
return cefSettings;
}
public String getCefFrameworkPathOSX() {
return cefFrameworkPathOSX;
}
public String getNativeBundlePath() {
return nativeBundlePath;
}
public SystemBootstrap.Loader getLoader() {
return loader;
}
public static JCefAppConfig getInstance(String nativeBundlePath) {
return getInstance(nativeBundlePath, false);
}
public static JCefAppConfig getInstance(String nativeBundlePath, boolean outOfProcess) {
JCefAppConfig appConfig = new JCefAppConfig() {
};
appConfig.nativeBundlePath = nativeBundlePath;
if (OS.isMacintosh()) {
appConfig.cefFrameworkPathOSX = Utils.pathOf(nativeBundlePath, "Frameworks/Chromium Embedded Framework.framework");
if (!outOfProcess) {
appConfig.appArgs.add("--framework-dir-path=" + appConfig.cefFrameworkPathOSX);
appConfig.appArgs.add("--main-bundle-path=" + Utils.pathOf(nativeBundlePath, "Frameworks/jcef Helper.app"));
appConfig.appArgs.add("--browser-subprocess-path=" + Utils.pathOf(nativeBundlePath, "Frameworks/jcef Helper.app/Contents/MacOS/jcef Helper"));
}
appConfig.appArgs.add("--disable-in-process-stack-traces");
appConfig.appArgs.add("--use-mock-keychain");
appConfig.appArgs.add("--disable-features=SpareRendererForSitePerProcess");
appConfig.appArgs.add("--disable-notifications");
// NOTE: some other switches are also could be usefull:
// "suppress-message-center-popups"
// "disable-infobars"
// "disable-notifications"
// "disable-push-api"
// "disable-default-apps"
// "deny-permission-prompts"
appConfig.loader = new SystemBootstrap.Loader() {
@Override
public void loadLibrary(String libname) {
libname = Utils.pathOf(nativeBundlePath, "lib" + libname + ".dylib");
System.load(libname);
}
};
} else if (OS.isLinux()) {
if (!outOfProcess) {
appConfig.cefSettings.browser_subprocess_path = Utils.pathOf(nativeBundlePath, "jcef_helper");
}
appConfig.cefSettings.resources_dir_path = Utils.pathOf(nativeBundlePath);
appConfig.cefSettings.locales_dir_path = Utils.pathOf(nativeBundlePath, "locales");
appConfig.loader = new SystemBootstrap.Loader() {
@Override
public void loadLibrary(String libname) {
libname = Utils.pathOf(nativeBundlePath, "lib" + libname + ".so");
System.load(libname);
}
};
} else if (OS.isWindows()) {
if (!outOfProcess) {
appConfig.cefSettings.browser_subprocess_path = Utils.pathOf(nativeBundlePath, "jcef_helper.exe");
}
appConfig.loader = new SystemBootstrap.Loader() {
final private Set<String> bundledLibs = new HashSet<>(Arrays.asList("chrome_elf", "jcef", "libcef", "shared_mem_helper"));
@Override
public void loadLibrary(String libname) {
if (bundledLibs.contains(libname)) {
System.load(Utils.pathOf(nativeBundlePath, libname + ".dll"));
} else {
System.loadLibrary(libname);
}
}
};
} else {
throw new IllegalStateException("JCEF is not supported on this platform: " + System.getProperty("os.name", "unknown"));
}
return appConfig;
}
/**
* @throws IllegalStateException in case of unsupported platform
*/
public static JCefAppConfig getInstance() {
JCefAppConfig appConfig = new JCefAppConfig() {
};
if (OS.isMacintosh()) {
String javaRoot = Utils.pathOf(System.getProperty("java.home"), "/..");
String frameworkPath = Utils.pathOf(javaRoot, "/Frameworks/Chromium Embedded Framework.framework");
String cefHelperPath = Utils.pathOf(javaRoot, "/Frameworks/jcef Helper.app");
String subprocessPath = Utils.pathOf(cefHelperPath, "/Contents/MacOS/jcef Helper");
appConfig.appArgs.add("--framework-dir-path=" + frameworkPath);
appConfig.appArgs.add("--browser-subprocess-path=" + subprocessPath);
appConfig.appArgs.add("--main-bundle-path=" + cefHelperPath);
appConfig.appArgs.add("--disable-in-process-stack-traces");
appConfig.appArgs.add("--use-mock-keychain");
appConfig.appArgs.add("--disable-features=SpareRendererForSitePerProcess");
appConfig.appArgs.add("--disable-notifications");
} else if (OS.isLinux()) {
String libPath = Utils.pathOf(System.getProperty("java.home"), "lib");
appConfig.cefSettings.resources_dir_path = libPath;
appConfig.cefSettings.locales_dir_path = Utils.pathOf(libPath, "locales");
appConfig.cefSettings.browser_subprocess_path = Utils.pathOf(libPath, "jcef_helper");
double scale = getDeviceScaleFactor(null);
appConfig.appArgs.add("--force-device-scale-factor=" + scale);
appConfig.appArgs.add("--disable-features=SpareRendererForSitePerProcess");
} else if (OS.isWindows()) {
String binPath = System.getProperty("java.home") + "/bin";
String libPath = System.getProperty("java.home") + "/lib";
appConfig.cefSettings.browser_subprocess_path = binPath + "/jcef_helper.exe";
appConfig.appArgs.add("--disable-features=SpareRendererForSitePerProcess");
} else {
throw new IllegalStateException("JCEF is not supported on this platform: " + System.getProperty("os.name", "unknown"));
}
appConfig.loader = new SystemBootstrap.Loader() {
@Override
public void loadLibrary(String libname) {
System.loadLibrary(libname);
}
};
return appConfig;
}
/**
* @deprecated don't use. This function is temporary here.
*/
@Deprecated
public static String getJbrFrameworkPathOSX() {
if (OS.isMacintosh()) {
return Utils.pathOf(System.getProperty("java.home"), "../Frameworks/Chromium Embedded Framework.framework");
}
return null;
}
/**
* Tries to load full JCEF version string from version.info file
*/
private static String getVersionEx() throws IOException {
try (InputStream inputStream = JCefAppConfig.class.getResourceAsStream("version.info")) {
return new BufferedReader(new InputStreamReader(inputStream)).readLine();
}
}
/**
* Returns the full version string before {@link org.cef.CefApp} is created.
* Otherwise use {@link CefApp#getVersion()}.
*/
public static String getVersion() {
try {
return getVersionEx();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* Returns runtime {@link JCefVersionDetails JCEF version details}
*/
public static JCefVersionDetails getVersionDetails() throws JCefVersionDetails.VersionUnavailableException {
try {
return new JCefVersionDetails(getVersionEx());
} catch (IOException e) {
throw new JCefVersionDetails.VersionUnavailableException("Unable to load version information", e);
}
}
public static double getDeviceScaleFactor(/*@Nullable*/Component component) {
if (GraphicsEnvironment.isHeadless()) {
return 1.0;
}
double scale = getForceDeviceScaleFactor();
if (scale > 0) return scale;
GraphicsDevice device = null;
try {
if (component != null && component.getGraphicsConfiguration() != null) {
device = component.getGraphicsConfiguration().getDevice();
} else {
device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
}
} catch (Throwable t) {
t.printStackTrace();
}
if (device != null) {
GraphicsConfiguration gc = device.getDefaultConfiguration();
if (gc != null) {
scale = gc.getDefaultTransform().getScaleX();
}
}
return scale;
}
/**
* Defined to support IDE-managed HiDPI mode in IDEA, undefined in JRE-managed HiDPI.
*/
@Deprecated
public static double getForceDeviceScaleFactor() {
if (forceDeviceScaleFactor.get() == 0) {
synchronized (forceDeviceScaleFactor) {
String prop = System.getProperty("jcef.forceDeviceScaleFactor");
if (prop != null) {
try {
forceDeviceScaleFactor.set(Double.parseDouble(prop));
} catch (NumberFormatException e) {
forceDeviceScaleFactor.set(Double.valueOf(-1));
e.printStackTrace();
}
} else {
forceDeviceScaleFactor.set(Double.valueOf(-1));
}
}
}
return forceDeviceScaleFactor.get();
}
public boolean isRemoteSupported() {
return nativeBundlePath != null || NativeServerManager.isRemoteSupported();
}
public boolean isRemoteEnabled() {
return isRemoteSupported() && Boolean.getBoolean("jcef.remote.enabled");
}
public File getServerExe() {
if (nativeBundlePath == null) {
return null;
} else if (OS.isMacintosh()) {
return new File(nativeBundlePath, "Frameworks/cef_server.app/Contents/MacOS/cef_server");
} else if (OS.isLinux()) {
return new File(nativeBundlePath, "cef_server");
} else if (OS.isWindows()) {
return new File(nativeBundlePath, "cef_server.exe");
}
throw new IllegalStateException("Unsupported platform: " + System.getProperty("os.name", "unknown"));
}
}