From 57b69f74beb1af06368532fa78b126b757ededc8 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 5 Sep 2016 18:13:40 +0200 Subject: [PATCH] notify about missed native lib on set --- .../src/nativeCredentialStore.kt | 57 ++++++++++++------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/platform/credential-store/src/nativeCredentialStore.kt b/platform/credential-store/src/nativeCredentialStore.kt index 8deb89b0a326..9953f45f04f2 100644 --- a/platform/credential-store/src/nativeCredentialStore.kt +++ b/platform/credential-store/src/nativeCredentialStore.kt @@ -22,6 +22,7 @@ import com.intellij.ide.passwordSafe.PasswordStorage import com.intellij.notification.NotificationGroup import com.intellij.notification.NotificationType import com.intellij.notification.SingletonNotificationManager +import com.intellij.openapi.application.ApplicationNamesInfo import com.intellij.openapi.application.ex.ApplicationInfoEx import com.intellij.openapi.diagnostic.catchAndLog import com.intellij.openapi.util.SystemInfo @@ -29,7 +30,7 @@ import com.intellij.util.SystemProperties import com.intellij.util.concurrency.QueueProcessor import com.intellij.util.containers.ContainerUtil -private val nullPassword = Credentials("\u0000", OneTimeString("\u0000")) +private val nullCredentials = Credentials("\u0000", OneTimeString("\u0000")) private val NOTIFICATION_MANAGER by lazy { // we use name "Password Safe" instead of "Credentials Store" because it was named so previously (and no much sense to rename it) @@ -39,15 +40,13 @@ private val NOTIFICATION_MANAGER by lazy { private class CredentialStoreWrapper(private val store: CredentialStore) : PasswordStorage { private val fallbackStore = lazy { KeePassCredentialStore(memoryOnly = true) } - private val queueProcessor = QueueProcessor<() -> Unit>({ - it() - }) + private val queueProcessor = QueueProcessor<() -> Unit>({ it() }) private val postponedCredentials = ContainerUtil.newConcurrentMap() override fun get(attributes: CredentialAttributes): Credentials? { postponedCredentials.get(attributes)?.let { - return if (it == nullPassword) null else it + return if (it == nullCredentials) null else it } var store = if (fallbackStore.isInitialized()) fallbackStore.value else store @@ -61,8 +60,7 @@ private class CredentialStoreWrapper(private val store: CredentialStore) : Passw } catch (e: UnsatisfiedLinkError) { store = fallbackStore.value - LOG.error(e) - NOTIFICATION_MANAGER.notify("Native Keychain is not used", "Failed to use native keychain — credentials will be stored in memory (until application is closed).") + notifyUnsatisfiedLinkError(e) return store.get(attributes) } catch (e: Throwable) { @@ -93,29 +91,44 @@ private class CredentialStoreWrapper(private val store: CredentialStore) : Passw } override fun set(attributes: CredentialAttributes, credentials: Credentials?) { - LOG.catchAndLog { - val store = if (fallbackStore.isInitialized()) fallbackStore.value else store - if (fallbackStore.isInitialized()) { + fun doSave() { + var store = if (fallbackStore.isInitialized()) fallbackStore.value else store + try { store.set(attributes, credentials) } + catch (e: UnsatisfiedLinkError) { + store = fallbackStore.value + notifyUnsatisfiedLinkError(e) + store.set(attributes, credentials) + } + catch (e: Throwable) { + LOG.error(e) + } + + postponedCredentials.remove(attributes) + } + + LOG.catchAndLog { + if (fallbackStore.isInitialized()) { + fallbackStore.value.set(attributes, credentials) + } else { - postponedCredentials.put(attributes, credentials ?: nullPassword) - queueProcessor.add { - if (!fallbackStore.isInitialized()) { - LOG.catchAndLog { - store.set(attributes, credentials) - postponedCredentials.remove(attributes) - return@add - } - } - fallbackStore.value.set(attributes, credentials) - postponedCredentials.remove(attributes) - } + postponedCredentials.put(attributes, credentials ?: nullCredentials) + queueProcessor.add { doSave() } } } } } +private fun notifyUnsatisfiedLinkError(e: UnsatisfiedLinkError) { + LOG.error(e) + var message = "Credentials are remembered until ${ApplicationNamesInfo.getInstance().fullProductName} is closed." + if (SystemInfo.isLinux) { + message += "\nPlease install required package libsecret-1-0: sudo apt-get install libsecret-1-0 gnome-keyring" + } + NOTIFICATION_MANAGER.notify("Cannot Access Native Keychain", message) +} + private class MacOsCredentialStoreFactory : CredentialStoreFactory { override fun create(): PasswordStorage? { if (isMacOsCredentialStoreSupported && SystemProperties.getBooleanProperty("use.mac.keychain", true)) {