Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/marius-wieschollek/passwords-webextension.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius David Wieschollek <passwords.public@mdns.eu>2021-02-28 12:57:33 +0300
committerMarius David Wieschollek <passwords.public@mdns.eu>2021-02-28 12:57:33 +0300
commit445cf8d9abf34bdce1ec25669a9a0deb81c5febe (patch)
treef9043274853db6f11926e15ac4afff1f4ae81ad6
parent2d04bf0f1f483b144e7e65a8ed8ef2b429916641 (diff)
parent94bf2d2c92b4bf73243ca33e2da21e264debe9d6 (diff)
[#155] Merge PR
Signed-off-by: Marius David Wieschollek <passwords.public@mdns.eu>
-rw-r--r--src/js/Controller/Clipboard/WriteClipboard.js21
-rw-r--r--src/js/Controller/Setting/Get.js2
-rw-r--r--src/js/Controller/Setting/Reset.js4
-rw-r--r--src/js/Controller/Setting/Set.js15
-rw-r--r--src/js/Manager/ClipboardManager.js124
-rw-r--r--src/js/Manager/ControllerManager.js7
-rw-r--r--src/js/Settings/MasterSettingsProvider.js12
-rw-r--r--src/platform/chrome/manifest.json4
-rw-r--r--src/platform/fenix/manifest.json3
-rw-r--r--src/platform/firefox/manifest.json3
-rw-r--r--src/platform/generic/_locales/de/messages.json24
-rw-r--r--src/platform/generic/_locales/en/messages.json22
-rw-r--r--src/vue/Components/List/Item/Password.vue8
-rw-r--r--src/vue/Components/Options/Settings.vue38
-rw-r--r--src/vue/Components/Tools/Generate.vue2
15 files changed, 278 insertions, 11 deletions
diff --git a/src/js/Controller/Clipboard/WriteClipboard.js b/src/js/Controller/Clipboard/WriteClipboard.js
new file mode 100644
index 0000000..de8d14b
--- /dev/null
+++ b/src/js/Controller/Clipboard/WriteClipboard.js
@@ -0,0 +1,21 @@
+import ClipboardManager from '@js/Manager/ClipboardManager';
+import AbstractController from '@js/Controller/AbstractController';
+import ErrorManager from "@js/Manager/ErrorManager";
+
+export default class WriteClipboard extends AbstractController {
+
+ /**
+ *
+ * @param {Message} message
+ * @param {Message} reply
+ */
+ async execute(message, reply) {
+ try {
+ let result = ClipboardManager.write(message.getPayload().type, message.getPayload().value);
+
+ if(result) reply.setPayload(true);
+ } catch(e) {
+ ErrorManager.logError(e)
+ }
+ }
+}
diff --git a/src/js/Controller/Setting/Get.js b/src/js/Controller/Setting/Get.js
index cea64a7..269693e 100644
--- a/src/js/Controller/Setting/Get.js
+++ b/src/js/Controller/Setting/Get.js
@@ -21,6 +21,8 @@ export default class Get extends AbstractController {
'theme.current',
'theme.custom',
'debug.localisation.enabled',
+ 'clipboard.clear.delay',
+ 'clipboard.clear.passwords',
'search.recommendation.mode',
'search.recommendation.maxRows'
];
diff --git a/src/js/Controller/Setting/Reset.js b/src/js/Controller/Setting/Reset.js
index 3d05c9c..ce66856 100644
--- a/src/js/Controller/Setting/Reset.js
+++ b/src/js/Controller/Setting/Reset.js
@@ -19,7 +19,9 @@ export default class Reset extends AbstractController {
'theme.custom',
'debug.localisation.enabled',
'search.recommendation.mode',
- 'search.recommendation.maxRows'
+ 'search.recommendation.maxRows',
+ 'clipboard.clear.passwords',
+ 'clipboard.clear.delay'
];
}
diff --git a/src/js/Controller/Setting/Set.js b/src/js/Controller/Setting/Set.js
index 7522560..8afeeb3 100644
--- a/src/js/Controller/Setting/Set.js
+++ b/src/js/Controller/Setting/Set.js
@@ -16,7 +16,8 @@ export default class Set extends AbstractController {
'popup.related.search',
'notification.password.new',
'notification.password.update',
- 'debug.localisation.enabled'
+ 'debug.localisation.enabled',
+ 'clipboard.clear.passwords'
];
}
@@ -40,6 +41,8 @@ export default class Set extends AbstractController {
await this._setSearchRecommendationMode(value);
} else if(setting === 'search.recommendation.maxRows') {
await this._setSearchRecommendationMaxRows(Number(value));
+ } else if(setting === 'clipboard.clear.delay') {
+ await this._setClipboardClearDelay(Number(value));
} else if(this._booleanSettings.indexOf(setting) !== -1) {
await this._setBoolean(setting, value);
} else {
@@ -115,4 +118,14 @@ export default class Set extends AbstractController {
async _setBoolean(setting, value) {
await SettingsService.set(setting, value === true);
}
+
+ /**
+ *
+ * @param {Number} value
+ * @return {Promise<void>}
+ * @private
+ */
+ async _setClipboardClearDelay(value) {
+ await SettingsService.set('clipboard.clear.delay', value);
+ }
} \ No newline at end of file
diff --git a/src/js/Manager/ClipboardManager.js b/src/js/Manager/ClipboardManager.js
new file mode 100644
index 0000000..6fb8009
--- /dev/null
+++ b/src/js/Manager/ClipboardManager.js
@@ -0,0 +1,124 @@
+import ErrorManager from '@js/Manager/ErrorManager';
+import SettingsService from '@js/Services/SettingsService';
+import SystemService from '@js/Services/SystemService';
+
+class ClipboardManager {
+
+ /**
+ *
+ * @return {Boolean}
+ */
+ async requestReadPermission() {
+ try {
+ return await SystemService.getBrowserApi().permissions.request({
+ permissions: ["clipboardRead"]
+ });
+ } catch (e) {
+ ErrorManager.logError(e, "ClipboardManager.getReadPermission()");
+ }
+ }
+
+ /**
+ *
+ * @return {Boolean}
+ */
+ async getReadPermissions() {
+ try {
+ return await SystemService.getBrowserApi().permissions.contains({
+ permissions: ["clipboardRead"]
+ });
+ } catch (e) {
+ ErrorManager.logError(e, "ClipboardManager.getReadPermission()");
+ }
+ }
+
+ /**
+ *
+ * @return {String}
+ */
+ async readText() {
+ try {
+ if(await SystemService.getBrowserApi().extension.getBackgroundPage() !== window) {
+ var permissions = await this.requestReadPermission();
+ }
+ if(permissions === true || await this.getReadPermissions()) {
+ var element = this._createDOMElement();
+ await document.execCommand('paste');
+ var result = element.value;
+ this._removeDOMElement(element);
+ return result;
+ }
+ } catch (e) {
+ ErrorManager.logError(e, "ClipboardManager.readText()");
+ }
+ }
+
+ /**
+ *
+ * @param {String} type
+ * @param {String} value
+ */
+ write(type, value) {
+ if(type === "password") {
+ this.writePassword(value);
+ }
+ else {
+ this.writeText(value);
+ }
+ }
+
+ /**
+ *
+ * @param {String} value
+ * @param {String} type
+ */
+ writeText(value) {
+ try {
+ var element = this._createDOMElement(value);
+ document.execCommand('copy', false, element.value);
+ this._removeDOMElement(element);
+ } catch (e) {
+ ErrorManager.logError(e);
+ }
+ }
+
+ /**
+ *
+ * @param {String} value
+ */
+ async writePassword(value) {
+ this.writeText(value);
+ if(await SettingsService.getValue('clipboard.clear.passwords') == true) {
+ setTimeout(async () => {
+ var current = await this.readText();
+ if(current === undefined || current === "" || current === value) {
+ this.writeText(" ");
+ }
+ }, Number(await SettingsService.getValue('clipboard.clear.delay')) * 1000)
+ }
+ }
+
+ /**
+ *
+ * @param {String} type
+ */
+ _createDOMElement(value = "", type = "text") {
+ var element = document.createElement("INPUT");
+ element.setAttribute("type", type);
+ element.setAttribute("value", value);
+ document.body.appendChild(element);
+ element.select();
+ return element;
+ }
+
+ /**
+ *
+ * @param {String} type
+ */
+ _removeDOMElement(element) {
+ element.blur();
+ document.body.removeChild(element);
+ }
+}
+
+export default new ClipboardManager(); \ No newline at end of file
diff --git a/src/js/Manager/ControllerManager.js b/src/js/Manager/ControllerManager.js
index 3d68736..61e683a 100644
--- a/src/js/Manager/ControllerManager.js
+++ b/src/js/Manager/ControllerManager.js
@@ -298,6 +298,13 @@ class ControllerManager {
await this._executeController(module, message, reply);
}
);
+ MessageService.listen(
+ 'clipboard.write',
+ async (message, reply) => {
+ let module = await import(/* webpackChunkName: "WriteClipboard" */ '@js/Controller/Clipboard/WriteClipboard');
+ await this._executeController(module, message, reply);
+ }
+ );
}
/**
diff --git a/src/js/Settings/MasterSettingsProvider.js b/src/js/Settings/MasterSettingsProvider.js
index 05c9b02..e424864 100644
--- a/src/js/Settings/MasterSettingsProvider.js
+++ b/src/js/Settings/MasterSettingsProvider.js
@@ -85,6 +85,14 @@ class MasterSettingsProvider {
'sync.search.recommendation.mode',
'local.search.recommendation.mode'
],
+ 'clipboard.clear.passwords' : [
+ 'sync.clipboard.clear.passwords',
+ 'local.clipboard.clear.passwords',
+ ],
+ 'clipboard.clear.delay' : [
+ 'sync.clipboard.clear.delay',
+ 'local.clipboard.clear.delay',
+ ]
};
this._defaults = {
'theme.custom' : null,
@@ -101,7 +109,9 @@ class MasterSettingsProvider {
'notification.password.update' : true,
'debug.localisation.enabled' : true,
'search.recommendation.mode' : 'host',
- 'search.recommendation.maxRows': 8
+ 'search.recommendation.maxRows': 8,
+ 'clipboard.clear.passwords' : false,
+ 'clipboard.clear.delay' : 60
};
}
diff --git a/src/platform/chrome/manifest.json b/src/platform/chrome/manifest.json
index c15924b..c2ca77b 100644
--- a/src/platform/chrome/manifest.json
+++ b/src/platform/chrome/manifest.json
@@ -49,9 +49,13 @@
"*://*/*",
"tabs",
"storage",
+ "clipboardWrite",
"contextMenus",
"notifications",
"webRequest",
"webRequestBlocking"
+ ],
+ "optional_permissions" : [
+ "clipboardRead"
]
} \ No newline at end of file
diff --git a/src/platform/fenix/manifest.json b/src/platform/fenix/manifest.json
index 21aac85..e1e299d 100644
--- a/src/platform/fenix/manifest.json
+++ b/src/platform/fenix/manifest.json
@@ -82,5 +82,8 @@
"clipboardWrite",
"webRequest",
"webRequestBlocking"
+ ],
+ "optional_permissions" : [
+ "clipboardRead"
]
} \ No newline at end of file
diff --git a/src/platform/firefox/manifest.json b/src/platform/firefox/manifest.json
index 5beb17b..38df3c7 100644
--- a/src/platform/firefox/manifest.json
+++ b/src/platform/firefox/manifest.json
@@ -90,5 +90,8 @@
"clipboardWrite",
"webRequest",
"webRequestBlocking"
+ ],
+ "optional_permissions" : [
+ "clipboardRead"
]
} \ No newline at end of file
diff --git a/src/platform/generic/_locales/de/messages.json b/src/platform/generic/_locales/de/messages.json
index 61c00be..ba8f7ef 100644
--- a/src/platform/generic/_locales/de/messages.json
+++ b/src/platform/generic/_locales/de/messages.json
@@ -103,6 +103,28 @@
"message" : "Antwortet auf HTTP Basic Authentication Anfragen mit dem ersten Eintrag der vorgeschlagenen Zugangsdaten. Dadurch können Zugangsdaten ungewollt an nicht vertrauenswürdige Server übermittelt werden.",
"description": "Help text in the extension settings for the setting to automatically respond with the first recommended credential to any http authentication auth request"
},
+ "SettingsClearClipboardPasswords" : {
+ "message" : "Zwischenablage nach einer bestimmten Zeit automatisch löschen",
+ "description": "Label of the setting in the extension settings to automatically clear passwords from clipboard after a certain time."
+ },
+ "HelpClearClipboardPasswords" : {
+ "message" : "Die Zwischenablage kann nur geleert werden, wenn noch mindestens ein Browserfenster offen ist.",
+ "description": "Help text in the extension settings for the setting to automatically clean passwords from clipboard after a certain time."
+ },
+ "SettingsClearClipboardDelay" : {
+ "message" : "Zwischenablage nach Ablauf folgender Zeit leeren (Sekunden)",
+ "description": "Label of the setting in the extension settings to define the time when the clipboard content will be removed."
+ },
+ "SettingsClipboardClearDelayOptions" : {
+ "message" : "$ROW$",
+ "description" : "Time in seconds until clipboard will get empty.",
+ "placeholders": {
+ "row": {
+ "content": "$1",
+ "example": "One of 15, 30, 45, 60, 90"
+ }
+ }
+ },
"NotificationSettings" : {
"message" : "Benachrichtigungen",
"description": "Headline above the notification section in the other settings tab in the extension settings"
@@ -1219,4 +1241,4 @@
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/platform/generic/_locales/en/messages.json b/src/platform/generic/_locales/en/messages.json
index c855735..4844909 100644
--- a/src/platform/generic/_locales/en/messages.json
+++ b/src/platform/generic/_locales/en/messages.json
@@ -103,6 +103,28 @@
"message" : "Automatically respond to http basic authentication requests with the first suggested credential. Be aware that this may expose credentials to untrustworthy servers.",
"description": "Help text in the extension settings for the setting to automatically respond with the first recommended credential to any http basic authentication request"
},
+ "SettingsClearClipboardPasswords" : {
+ "message" : "Automatically empty clipboard after a certain time",
+ "description": "Label of the setting in the extension settings to automatically clear passwords from clipboard after a certain time."
+ },
+ "HelpClearClipboardPasswords" : {
+ "message" : "This feature will not clear the clipboard if you close all browser windows before the timeout is reached!",
+ "description": "Help text in the extension settings for the setting to automatically clean passwords from clipboard after a certain time."
+ },
+ "SettingsClearClipboardDelay" : {
+ "message" : "Empty clipboard after the defined time (seconds)",
+ "description": "Label of the setting in the extension settings to define the time when the clipboard content will be removed."
+ },
+ "SettingsClipboardClearDelayOptions" : {
+ "message" : "$ROW$",
+ "description" : "Time in seconds until clipboard will get empty.",
+ "placeholders": {
+ "row": {
+ "content": "$1",
+ "example": "One of 15, 30, 45, 60, 90"
+ }
+ }
+ },
"NotificationSettings" : {
"message" : "Notifications",
"description": "Headline above the notification section in the other settings tab in the extension settings"
diff --git a/src/vue/Components/List/Item/Password.vue b/src/vue/Components/List/Item/Password.vue
index 28d59ea..7e99be1 100644
--- a/src/vue/Components/List/Item/Password.vue
+++ b/src/vue/Components/List/Item/Password.vue
@@ -5,8 +5,8 @@
{{ password.getLabel() }}
</div>
<div class="options">
- <icon icon="user" hover-icon="clipboard" @click="copy('username')" draggable="true" @dragstart="drag($event, 'username')"/>
- <icon icon="key" font="solid" hover-icon="clipboard" hover-font="regular" @click="copy('password')" draggable="true" @dragstart="drag($event, 'password')"/>
+ <icon icon="user" hover-icon="clipboard" @click="copy('username', 'text')" draggable="true" @dragstart="drag($event, 'username')"/>
+ <icon icon="key" font="solid" hover-icon="clipboard" hover-font="regular" @click="copy('password', 'password')" draggable="true" @dragstart="drag($event, 'password')"/>
</div>
<icon :class="securityClass" icon="shield-alt" font="solid"/>
</li>
@@ -92,9 +92,9 @@
ErrorManager.logError(e);
}
},
- copy(property) {
+ copy(property, type) {
let data = this.password.getProperty(property);
- navigator.clipboard.writeText(data);
+ MessageService.send({type: 'clipboard.write', payload: {type: type, value: data}}).catch(ErrorManager.catch);
let label = property.capitalize();
if(['password', 'username', 'url'].indexOf(property) === -1) {
diff --git a/src/vue/Components/Options/Settings.vue b/src/vue/Components/Options/Settings.vue
index 1eade48..ad6162c 100644
--- a/src/vue/Components/Options/Settings.vue
+++ b/src/vue/Components/Options/Settings.vue
@@ -23,6 +23,15 @@
<translate tag="label" for="paste-basic-auth" say="SettingsPasteBasicAuth"/>
<help-text type="warning" text="HelpPasteBasicAuth"/>
</div>
+ <div class="setting">
+ <slider-field id="clipboard-clear-passwords" v-model="clearClipboard"/>
+ <translate tag="label" for="clipboard-clear-passwords" say="SettingsClearClipboardPasswords"/>
+ <help-text type="warning" text="HelpClearClipboardPasswords"/>
+ </div>
+ <div class="setting">
+ <translate tag="label" for="clipboard-clear-delay" say="SettingsClearClipboardDelay"/>
+ <select-field id="clipboard-clear-delay" :options="clearClipboardDelayOptions" v-model="clearClipboardDelay"/>
+ </div>
<translate tag="h3" say="NotificationSettings"/>
<div class="setting">
@@ -61,6 +70,8 @@
import SliderField from "@vue/Components/Form/SliderField";
import SelectField from "@vue/Components/Form/SelectField";
import HelpText from "@vue/Components/Options/Setting/HelpText";
+ import ClipboardManager from '@js/Manager/ClipboardManager';
+
export default {
components: {HelpText, SliderField, SelectField, Translate},
@@ -75,7 +86,9 @@
relatedSearch : false,
notifyPwUpdate : false,
recSearchMode : 'host',
- recSearchRows : 8
+ recSearchRows : 8,
+ clearClipboard : false,
+ clearClipboardDelay: 60
};
},
@@ -110,7 +123,15 @@
for(i =1; i <= 20; i++) {
result.push({id: i, label: ['SearchRecommendationMaxRowsNumber', i]});
}
- return result;
+ return result;
+ },
+ clearClipboardDelayOptions() {
+ var i = 1;
+ var result = [];
+ for(let i of [15, 30, 45, 60, 90]) {
+ result.push({id: i, label: ['SettingsClipboardClearDelayOptions', i]});
+ }
+ return result;
}
},
@@ -126,6 +147,8 @@
this.getSetting('notification.password.update', 'notifyPwUpdate');
this.getSetting('search.recommendation.mode', 'recSearchMode');
this.getSetting('search.recommendation.maxRows', 'recSearchRows');
+ this.getSetting('clipboard.clear.passwords', 'clearClipboard');
+ this.getSetting('clipboard.clear.delay', 'clearClipboardDelay');
},
async getSetting(name, variable) {
try {
@@ -171,6 +194,17 @@
this.setSetting('paste.basic-auth', value);
}
},
+ clearClipboard(value, oldValue) {
+ if(value === true) ClipboardManager.requestReadPermission();
+ if(oldValue !== null && value !== oldValue) {
+ this.setSetting('clipboard.clear.passwords', value);
+ }
+ },
+ clearClipboardDelay(value, oldValue) {
+ if(oldValue !== null && value !== oldValue) {
+ this.setSetting('clipboard.clear.delay', value);
+ }
+ },
relatedSearch(value, oldValue) {
if(oldValue !== null && value !== oldValue) {
this.setSetting('popup.related.search', value);
diff --git a/src/vue/Components/Tools/Generate.vue b/src/vue/Components/Tools/Generate.vue
index ba1c55a..61e6aef 100644
--- a/src/vue/Components/Tools/Generate.vue
+++ b/src/vue/Components/Tools/Generate.vue
@@ -101,7 +101,7 @@
copy() {
let data = this.password,
label = LocalisationService.translate('PropertyPassword');
- navigator.clipboard.writeText(data);
+ MessageService.send({type: 'clipboard.write', payload: {type: 'password', value: data}}).catch(ErrorManager.catch);
ToastService
.success(['PasswordPropertyCopied', label])