mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 23:39:07 +07:00
[platform] postponing plugin privacy dialog till the next start when installing plugins in headless mode (IDEA-259912)
GitOrigin-RevId: e80c71a52e4b1685f163bd860e8ac6aad0960bbf
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b44eb87130
commit
609aa2e00a
@@ -73,4 +73,13 @@ failed.to.make.the.following.files.writable.error.message=Failed to make the fol
|
||||
failed.to.make.file.writable.error.message=Failed to make {0} writable.
|
||||
|
||||
vfs.corruption.notification.title=File system caches corrupted
|
||||
vfs.corruption.notification.text=Restart is required to rebuild corrupted caches
|
||||
vfs.corruption.notification.text=Restart is required to rebuild corrupted caches
|
||||
|
||||
third.party.plugins.privacy.note.title=Third-Party Plugins Privacy Note
|
||||
third.party.plugins.privacy.note.text=<html><body>The following plugins aren''t coming from JetBrains:<br><br>\
|
||||
{0}<br><br>\
|
||||
Using third-party plugins may involve a plugin vendor processing your personal data.<br>\
|
||||
Please check the plugin vendor\u2019s documentation for details concerning personal data processing.<br><br>\
|
||||
JetBrains is not responsible for any processing of your personal data by any third-party plugin vendors.</body></html>
|
||||
third.party.plugins.privacy.note.accept=Accept
|
||||
third.party.plugins.privacy.note.disable=Disable Plugins
|
||||
|
||||
@@ -4,10 +4,9 @@ package com.intellij.ide.plugins;
|
||||
import com.intellij.ReviseWhenPortedToJDK;
|
||||
import com.intellij.core.CoreBundle;
|
||||
import com.intellij.diagnostic.*;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.plugins.cl.PluginAwareClassLoader;
|
||||
import com.intellij.ide.plugins.cl.PluginClassLoader;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationInfoEx;
|
||||
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.PluginDescriptor;
|
||||
@@ -17,6 +16,7 @@ import com.intellij.openapi.util.BuildNumber;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.openapi.util.io.NioFiles;
|
||||
import com.intellij.openapi.util.text.HtmlChunk;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
@@ -24,6 +24,7 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.lang.UrlClassLoader;
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
@@ -39,6 +40,7 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
/**
|
||||
* See <a href="https://github.com/JetBrains/intellij-community/blob/master/docs/plugin.md">Plugin Model</a> documentation.
|
||||
@@ -48,8 +50,8 @@ import java.util.stream.Stream;
|
||||
public final class PluginManagerCore {
|
||||
public static final @NonNls String META_INF = "META-INF/";
|
||||
|
||||
public static final PluginId CORE_ID = PluginId.getId("com.intellij");
|
||||
public static final String CORE_PLUGIN_ID = "com.intellij";
|
||||
public static final PluginId CORE_ID = PluginId.getId(CORE_PLUGIN_ID);
|
||||
|
||||
public static final PluginId JAVA_PLUGIN_ID = PluginId.getId("com.intellij.java");
|
||||
static final PluginId JAVA_MODULE_ID = PluginId.getId("com.intellij.modules.java");
|
||||
@@ -74,6 +76,9 @@ public final class PluginManagerCore {
|
||||
private static final boolean IGNORE_DISABLED_PLUGINS = Boolean.getBoolean("idea.ignore.disabled.plugins");
|
||||
private static final MethodType HAS_LOADED_CLASS_METHOD_TYPE = MethodType.methodType(boolean.class, String.class);
|
||||
|
||||
private static final String THIRD_PARTY_PLUGINS_FILE = "alien_plugins.txt";
|
||||
private static volatile @Nullable Boolean ourThirdPartyPluginsNoteAccepted = null;
|
||||
|
||||
private static Reference<Map<PluginId, Set<String>>> brokenPluginVersions;
|
||||
private static volatile @Nullable PluginSet pluginSet;
|
||||
private static Map<PluginId, PluginLoadingError> pluginLoadingErrors;
|
||||
@@ -338,13 +343,7 @@ public final class PluginManagerCore {
|
||||
}
|
||||
|
||||
public static boolean isDevelopedByJetBrains(@NotNull PluginDescriptor plugin) {
|
||||
String vendor = plugin.getVendor();
|
||||
return isDevelopedByJetBrains(vendor) ||
|
||||
(vendor == null && // a core plugin
|
||||
!(plugin.getPluginClassLoader() instanceof PluginClassLoader) &&
|
||||
plugin instanceof IdeaPluginDescriptorImpl &&
|
||||
!((IdeaPluginDescriptorImpl)plugin).isUseIdeaClassLoader &&
|
||||
ApplicationInfoEx.getInstanceEx().isVendorJetBrains());
|
||||
return CORE_ID.equals(plugin.getPluginId()) || SPECIAL_IDEA_PLUGIN_ID.equals(plugin.getPluginId()) || isDevelopedByJetBrains(plugin.getVendor());
|
||||
}
|
||||
|
||||
public static boolean isDevelopedByJetBrains(@Nullable String vendorString) {
|
||||
@@ -799,6 +798,23 @@ public final class PluginManagerCore {
|
||||
Collections.singletonList(CORE_ID + " (platform prefix: " + System.getProperty(PlatformUtils.PLATFORM_PREFIX_KEY) + ")"));
|
||||
}
|
||||
|
||||
Collection<? extends IdeaPluginDescriptor> aliens = get3rdPartyPlugins(idMap);
|
||||
if (!aliens.isEmpty()) {
|
||||
if (GraphicsEnvironment.isHeadless()) {
|
||||
getLogger().info("3rd-party plugin privacy note not accepted yet; disabling plugins for this headless session");
|
||||
aliens.forEach(descriptor -> descriptor.setEnabled(false));
|
||||
}
|
||||
else if (!ask3rdPartyPluginsPrivacyConsent(aliens)) {
|
||||
getLogger().info("3rd-party plugin privacy note declined; disabling plugins");
|
||||
aliens.forEach(descriptor -> descriptor.setEnabled(false));
|
||||
PluginEnabler.HEADLESS.disableById(aliens.stream().map(descriptor -> descriptor.getPluginId()).collect(Collectors.toSet()));
|
||||
ourThirdPartyPluginsNoteAccepted = Boolean.FALSE;
|
||||
}
|
||||
else {
|
||||
ourThirdPartyPluginsNoteAccepted = Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
PluginSetBuilder pluginSetBuilder = new PluginSetBuilder(loadingResult.getEnabledPlugins());
|
||||
disableIncompatiblePlugins(pluginSetBuilder, idMap, pluginErrorsById);
|
||||
pluginSetBuilder.checkPluginCycles(globalErrors);
|
||||
@@ -837,6 +853,56 @@ public final class PluginManagerCore {
|
||||
return new PluginManagerState(pluginSet, disabledRequired, disabledAfterInit);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
static @Nullable Boolean isThirdPartyPluginsNoteAccepted() {
|
||||
Boolean result = ourThirdPartyPluginsNoteAccepted;
|
||||
ourThirdPartyPluginsNoteAccepted = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
static synchronized void write3rdPartyPlugins(@NotNull Collection<? extends IdeaPluginDescriptor> aliens) {
|
||||
Path file = Paths.get(PathManager.getConfigPath(), THIRD_PARTY_PLUGINS_FILE);
|
||||
try {
|
||||
NioFiles.createDirectories(file.getParent());
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.APPEND)) {
|
||||
//noinspection SSBasedInspection
|
||||
writePluginsList(aliens.stream().map(PluginDescriptor::getPluginId).collect(Collectors.toList()), writer);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
getLogger().error(file.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Collection<IdeaPluginDescriptorImpl> get3rdPartyPlugins(Map<PluginId, IdeaPluginDescriptorImpl> descriptors) {
|
||||
Path file = Paths.get(PathManager.getConfigPath(), THIRD_PARTY_PLUGINS_FILE);
|
||||
if (Files.exists(file)) {
|
||||
try {
|
||||
List<String> ids = Files.readAllLines(file);
|
||||
Files.delete(file);
|
||||
return ids.stream().map(id -> descriptors.get(PluginId.getId(id))).filter(descriptor -> descriptor != null).collect(Collectors.toList());
|
||||
}
|
||||
catch (IOException e) {
|
||||
getLogger().error(file.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static boolean ask3rdPartyPluginsPrivacyConsent(Iterable<? extends IdeaPluginDescriptor> descriptors) {
|
||||
String title = CoreBundle.message("third.party.plugins.privacy.note.title");
|
||||
String pluginList = StreamSupport.stream(descriptors.spliterator(), false)
|
||||
.map(descriptor -> " " + descriptor.getName() + " (" + descriptor.getVendor() + ')')
|
||||
.collect(Collectors.joining("<br>"));
|
||||
String text = CoreBundle.message("third.party.plugins.privacy.note.text", pluginList);
|
||||
String[] buttons = {CoreBundle.message("third.party.plugins.privacy.note.accept"), CoreBundle.message("third.party.plugins.privacy.note.disable")};
|
||||
int choice = JOptionPane.showOptionDialog(null, text, title, JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE,
|
||||
AllIcons.General.WarningDialog, buttons, buttons[0]);
|
||||
return choice == 0;
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
private static @Nullable Map<PluginId, List<IdeaPluginDescriptorImpl>> checkAndPut(@NotNull IdeaPluginDescriptorImpl descriptor,
|
||||
@NotNull PluginId id,
|
||||
|
||||
@@ -1002,13 +1002,6 @@ run.anything.context.separator.modules=Modules
|
||||
run.anything.context.tooltip=Choose context the current command will be executed in
|
||||
run.anything.accessible.name=Run anything
|
||||
|
||||
third.party.plugins.privacy.note.title=Third-Party Plugins Privacy Note
|
||||
third.party.plugins.privacy.note.message=<html><body>Using third-party plugins may involve a plugin vendor processing your personal data.<br>\
|
||||
Please check the plugin vendor\u2019s documentation for details concerning personal data processing.<br><br>\
|
||||
JetBrains is not responsible for any processing of your personal data by any third-party plugin vendors.</body></html>
|
||||
third.party.plugins.privacy.note.yes=Accept
|
||||
third.party.plugins.privacy.note.no=Cancel
|
||||
|
||||
plugin.signature.not.signed=<html><body>The ''{0}'' plugin has not been digitally signed, and its authenticity cannot be verified. Installing or updating unsigned plugins may expose your system to risk.<br/><br/>Plugin details: Id: {1} Version: {2} {3}</body></html>
|
||||
jetbrains.certificate.not.found=JetBrains certificate is not found.
|
||||
jetbrains.certificate.vendor=Vendor: {0}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.ide.plugins;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.core.CoreBundle;
|
||||
import com.intellij.ide.BrowserUtil;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.ide.plugins.marketplace.statistics.PluginManagerUsageCollector;
|
||||
import com.intellij.ide.plugins.marketplace.statistics.enums.DialogAcceptanceResultEnum;
|
||||
import com.intellij.idea.Main;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationAction;
|
||||
import com.intellij.notification.NotificationType;
|
||||
@@ -44,6 +47,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class PluginManagerMain {
|
||||
private PluginManagerMain() { }
|
||||
@@ -298,31 +302,50 @@ public final class PluginManagerMain {
|
||||
.notify(project);
|
||||
}
|
||||
|
||||
public static boolean checkThirdPartyPluginsAllowed(@NotNull Iterable<? extends IdeaPluginDescriptor> descriptors) {
|
||||
public static boolean checkThirdPartyPluginsAllowed(@NotNull Collection<? extends IdeaPluginDescriptor> descriptors) {
|
||||
@SuppressWarnings("SSBasedInspection") Collection<? extends IdeaPluginDescriptor> aliens = descriptors.stream()
|
||||
.filter(descriptor -> !(descriptor.isBundled() || PluginManagerCore.isDevelopedByJetBrains(descriptor)))
|
||||
.collect(Collectors.toList());
|
||||
if (aliens.isEmpty()) return true;
|
||||
|
||||
UpdateSettings updateSettings = UpdateSettings.getInstance();
|
||||
if (updateSettings.isThirdPartyPluginsAllowed()) {
|
||||
PluginManagerUsageCollector.thirdPartyAcceptanceCheck(DialogAcceptanceResultEnum.AUTO_ACCEPTED);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (IdeaPluginDescriptor descriptor : descriptors) {
|
||||
if (!PluginManagerCore.isDevelopedByJetBrains(descriptor)) {
|
||||
String title = IdeBundle.message("third.party.plugins.privacy.note.title");
|
||||
String message = IdeBundle.message("third.party.plugins.privacy.note.message");
|
||||
String yesText = IdeBundle.message("third.party.plugins.privacy.note.yes");
|
||||
String noText = IdeBundle.message("third.party.plugins.privacy.note.no");
|
||||
if (Messages.showYesNoDialog(message, title, yesText, noText, Messages.getWarningIcon()) == Messages.YES) {
|
||||
updateSettings.setThirdPartyPluginsAllowed(true);
|
||||
PluginManagerUsageCollector.thirdPartyAcceptanceCheck(DialogAcceptanceResultEnum.ACCEPTED);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
PluginManagerUsageCollector.thirdPartyAcceptanceCheck(DialogAcceptanceResultEnum.DECLINED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (Main.isHeadless()) {
|
||||
// postponing the dialog till the next start
|
||||
PluginManagerCore.write3rdPartyPlugins(aliens);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
String title = CoreBundle.message("third.party.plugins.privacy.note.title");
|
||||
String pluginList = aliens.stream()
|
||||
.map(descriptor -> " " + descriptor.getName() + " (" + descriptor.getVendor() + ')')
|
||||
.collect(Collectors.joining("<br>"));
|
||||
String message = CoreBundle.message("third.party.plugins.privacy.note.text", pluginList);
|
||||
String yesText = CoreBundle.message("third.party.plugins.privacy.note.accept"), noText = CommonBundle.getCancelButtonText();
|
||||
if (Messages.showYesNoDialog(message, title, yesText, noText, Messages.getWarningIcon()) == Messages.YES) {
|
||||
updateSettings.setThirdPartyPluginsAllowed(true);
|
||||
PluginManagerUsageCollector.thirdPartyAcceptanceCheck(DialogAcceptanceResultEnum.ACCEPTED);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
PluginManagerUsageCollector.thirdPartyAcceptanceCheck(DialogAcceptanceResultEnum.DECLINED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void checkThirdPartyPluginsAllowed() {
|
||||
Boolean noteAccepted = PluginManagerCore.isThirdPartyPluginsNoteAccepted();
|
||||
if (noteAccepted == Boolean.TRUE) {
|
||||
UpdateSettings.getInstance().setThirdPartyPluginsAllowed(true);
|
||||
PluginManagerUsageCollector.thirdPartyAcceptanceCheck(DialogAcceptanceResultEnum.ACCEPTED);
|
||||
}
|
||||
else if (noteAccepted == Boolean.FALSE) {
|
||||
PluginManagerUsageCollector.thirdPartyAcceptanceCheck(DialogAcceptanceResultEnum.DECLINED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,7 @@ import com.intellij.diagnostic.*
|
||||
import com.intellij.diagnostic.StartUpMeasurer.Activities
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.ide.*
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptorImpl
|
||||
import com.intellij.ide.plugins.PluginManagerCore
|
||||
import com.intellij.ide.plugins.PluginSet
|
||||
import com.intellij.ide.plugins.StartupAbortedException
|
||||
import com.intellij.ide.plugins.*
|
||||
import com.intellij.ide.ui.laf.darcula.DarculaLaf
|
||||
import com.intellij.openapi.application.*
|
||||
import com.intellij.openapi.application.ex.ApplicationEx
|
||||
@@ -186,6 +183,8 @@ private fun startApp(app: ApplicationImpl,
|
||||
addActivateAndWindowsCliListeners()
|
||||
initAppActivity.end()
|
||||
|
||||
PluginManagerMain.checkThirdPartyPluginsAllowed()
|
||||
|
||||
if (starter.requiredModality == ApplicationStarter.NOT_IN_EDT) {
|
||||
starter.main(args)
|
||||
// no need to use pool once plugins are loaded
|
||||
|
||||
Reference in New Issue
Block a user