passbolt-browser-extension 5.2.0 → 5.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +79 -1
- package/Gruntfile.js +1 -1
- package/RELEASE_NOTES.md +27 -71
- package/doc/browser-extension-class-diagram.md +9 -0
- package/package.json +5 -5
- package/src/all/_locales/sl/messages.json +2 -2
- package/src/all/background_page/controller/clipboard/cancelClipboardContentFlushController.js +51 -0
- package/src/all/background_page/controller/clipboard/cancelClipboardContentFlushController.test.js +46 -0
- package/src/all/background_page/controller/clipboard/copyTemporarilyToClipboardController.js +53 -0
- package/src/all/background_page/controller/clipboard/copyTemporarilyToClipboardController.test.js +47 -0
- package/src/all/background_page/controller/clipboard/{clipboardController.js → copyToClipboardController.js} +8 -8
- package/src/all/background_page/controller/clipboard/copyToClipboardController.test.js +47 -0
- package/src/all/background_page/controller/extension/getExtensionVersionController.test.js +1 -1
- package/src/all/background_page/controller/metadata/getOrFindMetadataKeysSettingsController.js +53 -0
- package/src/all/background_page/controller/metadata/getOrFindMetadataKeysSettingsController.test.js +106 -0
- package/src/all/background_page/controller/resource/updateResourceLocalStorageByFolderParentIdController.js +70 -0
- package/src/all/background_page/controller/resource/updateResourceLocalStorageByFolderParentIdController.test.js +78 -0
- package/src/all/background_page/controller/share/shareOneFolderController.test.js +2 -1
- package/src/all/background_page/controller/share/shareResourcesController.test.js +1 -1
- package/src/all/background_page/controller/user/deleteDryRunUserController.js +73 -0
- package/src/all/background_page/controller/user/deleteDryRunUserController.test.js +129 -0
- package/src/all/background_page/controller/user/deleteUserController.js +76 -0
- package/src/all/background_page/controller/user/deleteUserController.test.js +141 -0
- package/src/all/background_page/event/actionLogEvents.js +5 -12
- package/src/all/background_page/event/appEvents.js +33 -0
- package/src/all/background_page/event/findAllForActionLogController.js +58 -0
- package/src/all/background_page/event/findAllForActionLogController.test.js +43 -0
- package/src/all/background_page/event/quickAccessEvents.js +32 -0
- package/src/all/background_page/event/resourceEvents.js +11 -0
- package/src/all/background_page/event/userEvents.js +7 -20
- package/src/all/background_page/event/webIntegrationEvents.js +11 -0
- package/src/all/background_page/model/actionLog/{actionLogModel.js → findActionLogService.js} +25 -5
- package/src/all/background_page/model/actionLog/findActionLogService.test.js +61 -0
- package/src/all/background_page/model/comment/commentModel.js +5 -5
- package/src/all/background_page/model/entity/actionLog/actionLogsCollection.test.data.js +18 -0
- package/src/all/background_page/model/entity/actionLog/defaultActionLogEntity.test.data.js +34 -0
- package/src/all/background_page/model/entity/resource/resourcesCollection.js +25 -0
- package/src/all/background_page/model/entity/resource/resourcesCollection.test.js +34 -0
- package/src/all/background_page/model/import/resources/resourcesKdbxImportParser.test.js +0 -1
- package/src/all/background_page/model/user/userModel.js +0 -60
- package/src/all/background_page/pagemod/appPagemod.js +0 -2
- package/src/all/background_page/pagemod/appPagemod.test.js +2 -6
- package/src/all/background_page/service/alarm/globalAlarmService.js +2 -0
- package/src/all/background_page/service/api/actionLog/{actionLogService.js → actionLogApiService.js} +5 -4
- package/src/all/background_page/service/api/actionLog/actionLogApiService.test.js +55 -0
- package/src/all/background_page/service/api/comment/{commentService.js → commentApiService.js} +6 -7
- package/src/all/background_page/service/api/comment/commentApiService.test.js +122 -0
- package/src/all/background_page/service/api/resource/resourceService.js +1 -0
- package/src/all/background_page/service/auth/postLogoutService.js +2 -0
- package/src/all/background_page/service/auth/postLogoutService.test.js +4 -1
- package/src/all/background_page/service/browser/browserService.js +22 -0
- package/src/all/background_page/service/clipboard/clipboardProviderService.js +40 -0
- package/src/all/background_page/service/clipboard/clipboardProviderService.test.js +61 -0
- package/src/all/background_page/service/clipboard/copyToClipboardService.js +123 -0
- package/src/all/background_page/service/clipboard/copyToClipboardService.test.js +174 -0
- package/src/all/background_page/service/resource/findAndUpdateResourcesLocalStorageService.js +52 -1
- package/src/all/background_page/service/resource/findAndUpdateResourcesLocalStorageService.test.js +100 -0
- package/src/all/background_page/service/resource/findResourcesService.js +53 -19
- package/src/all/background_page/service/resource/findResourcesService.test.js +191 -0
- package/src/all/background_page/service/resourceType/updateResourceTypesService.test.js +1 -1
- package/src/all/background_page/service/share/shareResourceService.test.js +1 -1
- package/src/all/background_page/service/user/deleteUserService.js +97 -0
- package/src/all/background_page/service/user/deleteUserService.test.js +178 -0
- package/src/all/locales/de-DE/common.json +2 -2
- package/src/all/locales/es-ES/common.json +2 -2
- package/src/all/locales/fr-FR/common.json +5 -5
- package/src/all/locales/it-IT/common.json +2 -2
- package/src/all/locales/ja-JP/common.json +2 -2
- package/src/all/locales/ko-KR/common.json +2 -2
- package/src/all/locales/lt-LT/common.json +2 -2
- package/src/all/locales/nl-NL/common.json +2 -2
- package/src/all/locales/pl-PL/common.json +5 -5
- package/src/all/locales/pt-BR/common.json +2 -2
- package/src/all/locales/ro-RO/common.json +2 -2
- package/src/all/locales/ru-RU/common.json +2 -2
- package/src/all/locales/sl-SI/common.json +33 -33
- package/src/all/locales/sv-SE/common.json +2 -2
- package/src/all/locales/uk-UA/common.json +3 -3
- package/src/chrome/manifest.json +1 -1
- package/src/chrome/polyfill/clipboard/edgeBackgroundPageClipboardService.js +31 -0
- package/src/chrome/polyfill/clipboard/edgeBackgroundPageClipboardService.test.js +51 -0
- package/src/chrome-mv3/index.js +3 -3
- package/src/chrome-mv3/manifest.json +1 -1
- package/src/chrome-mv3/offscreens/{fetch.html → offscreen.html} +1 -1
- package/src/chrome-mv3/offscreens/{fetch.js → offscreen.js} +2 -2
- package/src/chrome-mv3/offscreens/service/clipboard/writeClipobardOffscreenService.js +54 -0
- package/src/chrome-mv3/offscreens/service/clipboard/writeClipobardOffscreenService.test.js +56 -0
- package/src/chrome-mv3/offscreens/service/network/fetchOffscreenService.js +36 -44
- package/src/chrome-mv3/offscreens/service/network/fetchOffscreenService.test.data.js +0 -1
- package/src/chrome-mv3/offscreens/service/network/fetchOffscreenService.test.js +90 -120
- package/src/chrome-mv3/offscreens/service/offscreen/handleOffscreenRequestService.js +85 -0
- package/src/chrome-mv3/offscreens/service/offscreen/handleOffscreenRequestService.test.js +99 -0
- package/src/chrome-mv3/polyfill/clipboardOffscreenPolyfill.js +19 -0
- package/src/chrome-mv3/serviceWorker/service/clipboard/requestClipboardOffscreenService.js +51 -0
- package/src/chrome-mv3/serviceWorker/service/clipboard/requestClipboardOffscreenService.test.js +70 -0
- package/src/chrome-mv3/serviceWorker/service/clipboard/responseClipboardOffscreenService.js +25 -0
- package/src/chrome-mv3/serviceWorker/service/clipboard/responseClipboardOffscreenService.test.data.js +21 -0
- package/src/chrome-mv3/serviceWorker/service/clipboard/responseClipboardOffscreenService.test.js +33 -0
- package/src/chrome-mv3/serviceWorker/service/network/requestFetchOffscreenService.js +25 -50
- package/src/chrome-mv3/serviceWorker/service/network/requestFetchOffscreenService.test.js +16 -39
- package/src/chrome-mv3/serviceWorker/service/network/responseFetchOffscreenService.js +14 -45
- package/src/chrome-mv3/serviceWorker/service/network/responseFetchOffscreenService.test.js +5 -37
- package/src/chrome-mv3/serviceWorker/service/offscreen/createOffscreenDocumentService.js +43 -0
- package/src/chrome-mv3/serviceWorker/service/offscreen/createOffscreenDocumentService.test.js +48 -0
- package/src/chrome-mv3/serviceWorker/service/offscreen/handleOffscreenResponseService.js +119 -0
- package/src/chrome-mv3/serviceWorker/service/offscreen/handleOffscreenResponseService.test.js +159 -0
- package/src/firefox/manifest.json +1 -1
- package/src/safari/manifest.json +1 -1
- package/test/jest.setup.js +4 -0
- package/test/mocks/mockNavigatorClipboard.js +40 -0
- package/test/mocks/mockWebExtensionPolyfill.js +2 -1
- package/{webpack-offscreens.fetch.config.js → webpack-offscreens.config.js} +1 -1
- package/webpack.service-worker.config.js +1 -0
- package/src/all/background_page/controller/clipboard/clipboardController.test.js +0 -68
- package/src/all/background_page/event/clipboardEvents.js +0 -28
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Passbolt ~ Open source password manager for teams
|
|
3
|
+
* Copyright (c) Passbolt SA (https://www.passbolt.com)
|
|
4
|
+
*
|
|
5
|
+
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
|
6
|
+
* For full copyright and license information, please see the LICENSE.txt
|
|
7
|
+
* Redistributions of files must retain the above copyright notice.
|
|
8
|
+
*
|
|
9
|
+
* @copyright Copyright (c) Passbolt SA (https://www.passbolt.com)
|
|
10
|
+
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
|
11
|
+
* @link https://www.passbolt.com Passbolt(tm)
|
|
12
|
+
* @since 5.3.2
|
|
13
|
+
*/
|
|
14
|
+
import {assertUuid} from "../../../../all/background_page/utils/assertions";
|
|
15
|
+
import {SEND_MESSAGE_TARGET_CLIPBOARD_WRITE_OFFSCREEN_RESPONSE_HANDLER} from "../../../offscreens/service/clipboard/writeClipobardOffscreenService";
|
|
16
|
+
import {
|
|
17
|
+
SEND_MESSAGE_TARGET_FETCH_OFFSCREEN_POLLING_HANDLER,
|
|
18
|
+
SEND_MESSAGE_TARGET_FETCH_OFFSCREEN_RESPONSE_HANDLER
|
|
19
|
+
} from "../../../offscreens/service/network/fetchOffscreenService";
|
|
20
|
+
import {SEND_MESSAGE_TARGET_OFFSCREEN_ERROR_RESPONSE_HANDLER} from "../../../offscreens/service/offscreen/handleOffscreenRequestService";
|
|
21
|
+
import ResponseClipboardOffscreenService from "../clipboard/responseClipboardOffscreenService";
|
|
22
|
+
import ResponseFetchOffscreenService from "../network/responseFetchOffscreenService";
|
|
23
|
+
|
|
24
|
+
export default class HandleOffscreenResponseService {
|
|
25
|
+
/**
|
|
26
|
+
* @type {object}
|
|
27
|
+
* @private
|
|
28
|
+
*/
|
|
29
|
+
static _offscreenResponsePromisesCallbacks = {};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @type {Map<string, function>}
|
|
33
|
+
* @private
|
|
34
|
+
*/
|
|
35
|
+
static REPONSE_HANDLE_MAP = {
|
|
36
|
+
[SEND_MESSAGE_TARGET_FETCH_OFFSCREEN_RESPONSE_HANDLER]: ResponseFetchOffscreenService.handleFetchResponse,
|
|
37
|
+
[SEND_MESSAGE_TARGET_CLIPBOARD_WRITE_OFFSCREEN_RESPONSE_HANDLER]: ResponseClipboardOffscreenService.handleClipboardResponse,
|
|
38
|
+
[SEND_MESSAGE_TARGET_OFFSCREEN_ERROR_RESPONSE_HANDLER]: HandleOffscreenResponseService.handleOffscreenError,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Handle offscreen response.
|
|
43
|
+
* @param {object} message Browser runtime.onMessage listener message.
|
|
44
|
+
*/
|
|
45
|
+
static handleOffscreenResponse(message) {
|
|
46
|
+
if (message.target === SEND_MESSAGE_TARGET_FETCH_OFFSCREEN_POLLING_HANDLER) {
|
|
47
|
+
//it's a polling message that is only here to keep the offscreen document alive.
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const responseHandler = HandleOffscreenResponseService.REPONSE_HANDLE_MAP[message.target];
|
|
52
|
+
if (!responseHandler) {
|
|
53
|
+
console.debug("HandleOffscreenResponseService received response not specific to offscreen.");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
HandleOffscreenResponseService._assertOffscreenResponse(message);
|
|
58
|
+
const promise = HandleOffscreenResponseService._consumeRequestPromiseCallbacksOrFail(message.id);
|
|
59
|
+
|
|
60
|
+
responseHandler(message, promise);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Handles generic offscreen error message.
|
|
65
|
+
* @param {object} message
|
|
66
|
+
* @param {{resolve: function, reject: function}} promise
|
|
67
|
+
* @private
|
|
68
|
+
*/
|
|
69
|
+
static handleOffscreenError(message, promise) {
|
|
70
|
+
const error = new Error("Something went wrong while processing an offscreen request");
|
|
71
|
+
|
|
72
|
+
const errorCauseString = message?.data?.error;
|
|
73
|
+
if (errorCauseString) {
|
|
74
|
+
const cause = JSON.parse(errorCauseString);
|
|
75
|
+
error.cause = new Error();
|
|
76
|
+
error.cause.name = cause.name;
|
|
77
|
+
error.cause.message = cause.message;
|
|
78
|
+
error.cause.stack = cause.stack;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
promise.reject(error);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Sets a new promise response callback for a given offscreen request id.
|
|
86
|
+
* @param {string} id
|
|
87
|
+
* @param {{resolve: function, reject: function}} promise
|
|
88
|
+
*/
|
|
89
|
+
static setResponseCallback(id, promise) {
|
|
90
|
+
HandleOffscreenResponseService._offscreenResponsePromisesCallbacks[id] = promise;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Asserts that the given message is a valid offscreen response message.
|
|
95
|
+
* @param {object} message
|
|
96
|
+
* @throws {Error} if message.id is not a valid UUID
|
|
97
|
+
* @private
|
|
98
|
+
*/
|
|
99
|
+
static _assertOffscreenResponse(message) {
|
|
100
|
+
assertUuid(message.id, "HandleOffscreenResponseService: message.id should be a valid uuid.");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Consume the offscreen request promise callbacks or fail.
|
|
105
|
+
* @param {string} id The identifier of the offscreen fetch request.
|
|
106
|
+
* @returns {Promise}
|
|
107
|
+
* @throws {Error} If no request promise callbacks can be found for the given offscreen fetch request id.
|
|
108
|
+
* @private
|
|
109
|
+
*/
|
|
110
|
+
static _consumeRequestPromiseCallbacksOrFail(id) {
|
|
111
|
+
const offscreenRequestPromiseCallback = HandleOffscreenResponseService._offscreenResponsePromisesCallbacks[id];
|
|
112
|
+
if (!offscreenRequestPromiseCallback) {
|
|
113
|
+
throw new Error("HandleOffscreenResponseService: No request promise callbacks found for the given offscreen fetch request id.");
|
|
114
|
+
}
|
|
115
|
+
delete HandleOffscreenResponseService._offscreenResponsePromisesCallbacks[id];
|
|
116
|
+
|
|
117
|
+
return offscreenRequestPromiseCallback;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Passbolt ~ Open source password manager for teams
|
|
3
|
+
* Copyright (c) Passbolt SA (https://www.passbolt.com)
|
|
4
|
+
*
|
|
5
|
+
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
|
6
|
+
* For full copyright and license information, please see the LICENSE.txt
|
|
7
|
+
* Redistributions of files must retain the above copyright notice.
|
|
8
|
+
*
|
|
9
|
+
* @copyright Copyright (c) Passbolt SA (https://www.passbolt.com)
|
|
10
|
+
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
|
11
|
+
* @link https://www.passbolt.com Passbolt(tm)
|
|
12
|
+
* @since 5.3.2
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import {SEND_MESSAGE_TARGET_CLIPBOARD_WRITE_OFFSCREEN_RESPONSE_HANDLER} from "../../../offscreens/service/clipboard/writeClipobardOffscreenService";
|
|
16
|
+
import {SEND_MESSAGE_TARGET_FETCH_OFFSCREEN_RESPONSE_HANDLER} from "../../../offscreens/service/network/fetchOffscreenService";
|
|
17
|
+
import {defaultCallbacks} from "../network/responseFetchOffscreenService.test.data";
|
|
18
|
+
import HandleOffscreenResponseService from "./handleOffscreenResponseService";
|
|
19
|
+
import {v4 as uuidv4} from "uuid";
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
jest.clearAllMocks();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe("HandleOffscreenResponseService", () => {
|
|
26
|
+
let fetchFunction, clipboardWriteFunction;
|
|
27
|
+
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
jest.clearAllMocks();
|
|
30
|
+
fetchFunction = jest.spyOn(HandleOffscreenResponseService.REPONSE_HANDLE_MAP, SEND_MESSAGE_TARGET_FETCH_OFFSCREEN_RESPONSE_HANDLER).mockImplementation(() => {});
|
|
31
|
+
clipboardWriteFunction = jest.spyOn(HandleOffscreenResponseService.REPONSE_HANDLE_MAP, SEND_MESSAGE_TARGET_CLIPBOARD_WRITE_OFFSCREEN_RESPONSE_HANDLER).mockImplementation(() => {});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe("::handleOffscreenResponse", () => {
|
|
35
|
+
it("should handle fetch response and dispatch to the right service", () => {
|
|
36
|
+
expect.assertions(3);
|
|
37
|
+
|
|
38
|
+
const message = {
|
|
39
|
+
id: uuidv4(),
|
|
40
|
+
target: "service-worker-fetch-offscreen-response-handler"
|
|
41
|
+
};
|
|
42
|
+
const promises = defaultCallbacks();
|
|
43
|
+
HandleOffscreenResponseService.setResponseCallback(message.id, promises);
|
|
44
|
+
|
|
45
|
+
HandleOffscreenResponseService.handleOffscreenResponse(message);
|
|
46
|
+
|
|
47
|
+
expect(fetchFunction).toHaveBeenCalledTimes(1);
|
|
48
|
+
expect(fetchFunction).toHaveBeenCalledWith(message, promises);
|
|
49
|
+
expect(clipboardWriteFunction).not.toHaveBeenCalled();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should handle fetch polling response and dispatch to the right service", () => {
|
|
53
|
+
expect.assertions(2);
|
|
54
|
+
|
|
55
|
+
const message = {
|
|
56
|
+
target: "service-worker-fetch-offscreen-polling-handler"
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
HandleOffscreenResponseService.handleOffscreenResponse(message);
|
|
60
|
+
|
|
61
|
+
expect(fetchFunction).not.toHaveBeenCalled();
|
|
62
|
+
expect(clipboardWriteFunction).not.toHaveBeenCalled();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should handle clipboard writeText and dispatch to the right service", () => {
|
|
66
|
+
expect.assertions(3);
|
|
67
|
+
|
|
68
|
+
const message = {
|
|
69
|
+
id: uuidv4(),
|
|
70
|
+
target: "service-worker-clipboard-write-text-offscreen-response-handler"
|
|
71
|
+
};
|
|
72
|
+
const promises = defaultCallbacks();
|
|
73
|
+
HandleOffscreenResponseService.setResponseCallback(message.id, promises);
|
|
74
|
+
|
|
75
|
+
HandleOffscreenResponseService.handleOffscreenResponse(message);
|
|
76
|
+
|
|
77
|
+
expect(clipboardWriteFunction).toHaveBeenCalledTimes(1);
|
|
78
|
+
expect(clipboardWriteFunction).toHaveBeenCalledWith(message, promises);
|
|
79
|
+
expect(fetchFunction).not.toHaveBeenCalled();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("should handle offscreen error message", () => {
|
|
83
|
+
expect.assertions(2);
|
|
84
|
+
|
|
85
|
+
const error = new Error("It went really bad somehow");
|
|
86
|
+
const expectedError = new Error("Something went wrong while processing an offscreen request");
|
|
87
|
+
expectedError.cause = error;
|
|
88
|
+
|
|
89
|
+
const message = {
|
|
90
|
+
id: uuidv4(),
|
|
91
|
+
target: "service-worker-offscreen-error-response-handler",
|
|
92
|
+
data: {error: JSON.stringify(error, Object.getOwnPropertyNames(error))},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const promises = defaultCallbacks();
|
|
96
|
+
|
|
97
|
+
HandleOffscreenResponseService.setResponseCallback(message.id, promises);
|
|
98
|
+
HandleOffscreenResponseService.handleOffscreenResponse(message);
|
|
99
|
+
|
|
100
|
+
expect(promises.reject).toHaveBeenCalledTimes(1);
|
|
101
|
+
expect(promises.reject).toHaveBeenCalledWith(expectedError);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("should ignore message with unknown target", () => {
|
|
105
|
+
expect.assertions(2);
|
|
106
|
+
|
|
107
|
+
const message = {target: "???"};
|
|
108
|
+
|
|
109
|
+
HandleOffscreenResponseService.handleOffscreenResponse(message);
|
|
110
|
+
|
|
111
|
+
expect(clipboardWriteFunction).not.toHaveBeenCalled();
|
|
112
|
+
expect(fetchFunction).not.toHaveBeenCalled();
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe("::_consumeRequestPromiseCallbacksOrFail", () => {
|
|
117
|
+
it("should consume the response handler associated to the given id", () => {
|
|
118
|
+
expect.assertions(3);
|
|
119
|
+
|
|
120
|
+
const id = crypto.randomUUID();
|
|
121
|
+
const callbacks = defaultCallbacks();
|
|
122
|
+
HandleOffscreenResponseService.setResponseCallback(id, callbacks);
|
|
123
|
+
|
|
124
|
+
const consumedCallbacks = HandleOffscreenResponseService._consumeRequestPromiseCallbacksOrFail(id);
|
|
125
|
+
|
|
126
|
+
expect(consumedCallbacks).not.toBeNull();
|
|
127
|
+
expect(consumedCallbacks).toEqual(callbacks);
|
|
128
|
+
expect(Object.keys(HandleOffscreenResponseService._offscreenResponsePromisesCallbacks).length).toEqual(0);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("should throw if no associated callbacks found for the given id", () => {
|
|
132
|
+
expect.assertions(1);
|
|
133
|
+
const id = crypto.randomUUID();
|
|
134
|
+
expect(() => HandleOffscreenResponseService._consumeRequestPromiseCallbacksOrFail(id)).toThrow();
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
describe("::handleOffscreenError", () => {
|
|
139
|
+
it("should reject the given promise with an error containing the cause of the offscreen process failure", () => {
|
|
140
|
+
expect.assertions(2);
|
|
141
|
+
|
|
142
|
+
const callbacks = defaultCallbacks();
|
|
143
|
+
const error = new Error("Something went wrong with the fetch");
|
|
144
|
+
const message = {
|
|
145
|
+
data: {
|
|
146
|
+
error: JSON.stringify(error, Object.getOwnPropertyNames(error))
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
};
|
|
150
|
+
const expectedError = new Error("Something went wrong while processing an offscreen request");
|
|
151
|
+
expectedError.cause = message.data.error;
|
|
152
|
+
|
|
153
|
+
HandleOffscreenResponseService.handleOffscreenError(message, callbacks);
|
|
154
|
+
|
|
155
|
+
expect(callbacks.reject).toHaveBeenCalledTimes(1);
|
|
156
|
+
expect(callbacks.reject).toHaveBeenCalledWith(expectedError);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
package/src/safari/manifest.json
CHANGED
package/test/jest.setup.js
CHANGED
|
@@ -19,6 +19,7 @@ import "./mocks/mockTextEncoder";
|
|
|
19
19
|
import "./mocks/mockCryptoKey";
|
|
20
20
|
import "./matchers/extendExpect";
|
|
21
21
|
import MockNavigatorLocks from './mocks/mockNavigatorLocks';
|
|
22
|
+
import MockNavigatorClipboard from './mocks/mockNavigatorClipboard';
|
|
22
23
|
import OrganizationSettingsModel from "../src/all/background_page/model/organizationSettings/organizationSettingsModel";
|
|
23
24
|
import {Config} from "../src/all/background_page/model/config";
|
|
24
25
|
import Keyring from "../src/all/background_page/model/keyring";
|
|
@@ -49,6 +50,9 @@ if (!global.navigator) {
|
|
|
49
50
|
if (!global.navigator.locks) {
|
|
50
51
|
global.navigator.locks = new MockNavigatorLocks();
|
|
51
52
|
}
|
|
53
|
+
if (!global.navigator.clipboard) {
|
|
54
|
+
global.navigator.clipboard = new MockNavigatorClipboard();
|
|
55
|
+
}
|
|
52
56
|
|
|
53
57
|
/*
|
|
54
58
|
* quick polyfill for jest to have stucturedClone function defined
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Passbolt ~ Open source password manager for teams
|
|
3
|
+
* Copyright (c) Passbolt SA (https://www.passbolt.com)
|
|
4
|
+
*
|
|
5
|
+
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
|
6
|
+
* For full copyright and license information, please see the LICENSE.txt
|
|
7
|
+
* Redistributions of files must retain the above copyright notice.
|
|
8
|
+
*
|
|
9
|
+
* @copyright Copyright (c) Passbolt SA (https://www.passbolt.com)
|
|
10
|
+
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
|
11
|
+
* @link https://www.passbolt.com Passbolt(tm)
|
|
12
|
+
* @since 5.3.2
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Mock class to be used in replacement of navigator.clipboard
|
|
17
|
+
*/
|
|
18
|
+
export default class MockNavigatorClipboard {
|
|
19
|
+
/**
|
|
20
|
+
* @type {string}
|
|
21
|
+
* @private
|
|
22
|
+
*/
|
|
23
|
+
_clipboardData = "";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @inheritDoc navigator.clipboard.readText
|
|
27
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/readText
|
|
28
|
+
*/
|
|
29
|
+
async readText() {
|
|
30
|
+
return this._clipboardData;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @inheritDoc navigator.clipboard.writeText
|
|
35
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText
|
|
36
|
+
*/
|
|
37
|
+
async writeText(newClipText) {
|
|
38
|
+
this._clipboardData = newClipText;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -42,7 +42,8 @@ jest.mock("webextension-polyfill", () => {
|
|
|
42
42
|
getURL: jest.fn(path => `chrome-extension://didegimhafipceonhjepacocaffmoppf/${path}`),
|
|
43
43
|
// Force extension version
|
|
44
44
|
getManifest: jest.fn(() => ({
|
|
45
|
-
version: "
|
|
45
|
+
version: "5.3.0",
|
|
46
|
+
manifest_version: 3,
|
|
46
47
|
})),
|
|
47
48
|
// Runtime primitives not mocked by jest-webextension-mock v3.8.9
|
|
48
49
|
OnInstalledReason: {
|
|
@@ -3,7 +3,7 @@ const TerserPlugin = require("terser-webpack-plugin");
|
|
|
3
3
|
|
|
4
4
|
const config = {
|
|
5
5
|
entry: {
|
|
6
|
-
'
|
|
6
|
+
'offscreen': path.resolve(__dirname, './src/chrome-mv3/offscreens/offscreen.js'),
|
|
7
7
|
},
|
|
8
8
|
mode: 'production',
|
|
9
9
|
module: {
|
|
@@ -13,6 +13,7 @@ const config = {
|
|
|
13
13
|
browser: path.resolve(__dirname, './src/all/common/polyfill/browserPolyfill.js'),
|
|
14
14
|
// Inject custom api client fetch to MV3 extension as workaround of the invalid certificate issue.
|
|
15
15
|
customApiClientFetch: path.resolve(__dirname, './src/chrome-mv3/polyfill/fetchOffscreenPolyfill.js'),
|
|
16
|
+
customNavigatorClipboard: path.resolve(__dirname, './src/chrome-mv3/polyfill/clipboardOffscreenPolyfill.js'),
|
|
16
17
|
})
|
|
17
18
|
],
|
|
18
19
|
module: {
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Passbolt ~ Open source password manager for teams
|
|
3
|
-
* Copyright (c) 2023 Passbolt SA (https://www.passbolt.com)
|
|
4
|
-
*
|
|
5
|
-
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
|
6
|
-
* For full copyright and license information, please see the LICENSE.txt
|
|
7
|
-
* Redistributions of files must retain the above copyright notice.
|
|
8
|
-
*
|
|
9
|
-
* @copyright Copyright (c) 2023 Passbolt SA (https://www.passbolt.com)
|
|
10
|
-
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
|
11
|
-
* @link https://www.passbolt.com Passbolt(tm)
|
|
12
|
-
* @since 3.9.0
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import ClipboardController from './clipboardController';
|
|
16
|
-
|
|
17
|
-
describe('ClipboardController', () => {
|
|
18
|
-
let controller, workerMock;
|
|
19
|
-
const toCopy = "text";
|
|
20
|
-
|
|
21
|
-
beforeEach(() => {
|
|
22
|
-
workerMock = {
|
|
23
|
-
port: {
|
|
24
|
-
emit: jest.fn()
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
navigator.clipboard = {
|
|
28
|
-
writeText: jest.fn()
|
|
29
|
-
};
|
|
30
|
-
controller = new ClipboardController(workerMock, 'request-id');
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
describe('constructor', () => {
|
|
34
|
-
it('should set the worker and requestId properties', () => {
|
|
35
|
-
expect.assertions(2);
|
|
36
|
-
expect(controller.worker).toBe(workerMock);
|
|
37
|
-
expect(controller.requestId).toBe('request-id');
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
describe('_exec', () => {
|
|
42
|
-
it('should call the exec method and emit a success message on the worker port', async() => {
|
|
43
|
-
expect.assertions(2);
|
|
44
|
-
const execSpy = jest.spyOn(controller, 'exec');
|
|
45
|
-
await controller._exec(toCopy);
|
|
46
|
-
expect(execSpy).toHaveBeenCalledWith(toCopy);
|
|
47
|
-
expect(workerMock.port.emit).toHaveBeenCalledWith('request-id', 'SUCCESS');
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('should emit an error message on the worker port if an error occurs', async() => {
|
|
51
|
-
expect.assertions(1);
|
|
52
|
-
const error = new Error('Some error');
|
|
53
|
-
jest.spyOn(controller, 'exec').mockImplementationOnce(() => {
|
|
54
|
-
throw error;
|
|
55
|
-
});
|
|
56
|
-
await controller._exec(toCopy);
|
|
57
|
-
expect(workerMock.port.emit).toHaveBeenCalledWith('request-id', 'ERROR', error);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe('exec', () => {
|
|
62
|
-
it('should call navigator.clipboard method of the QuickAccessService', () => {
|
|
63
|
-
expect.assertions(1);
|
|
64
|
-
controller.exec(toCopy);
|
|
65
|
-
expect(navigator.clipboard.writeText).toHaveBeenCalledWith('text');
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
});
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Passbolt ~ Open source password manager for teams
|
|
3
|
-
* Copyright (c) 2023 Passbolt SA (https://www.passbolt.com)
|
|
4
|
-
*
|
|
5
|
-
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
|
6
|
-
* For full copyright and license information, please see the LICENSE.txt
|
|
7
|
-
* Redistributions of files must retain the above copyright notice.
|
|
8
|
-
*
|
|
9
|
-
* @copyright Copyright (c) 2023 Passbolt SA (https://www.passbolt.com)
|
|
10
|
-
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
|
11
|
-
* @link https://www.passbolt.com Passbolt(tm)
|
|
12
|
-
* @since 3.9.0
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import ClipboardController from '../controller/clipboard/clipboardController';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Listens the clipboard events
|
|
19
|
-
* @param worker
|
|
20
|
-
*/
|
|
21
|
-
const listen = function(worker) {
|
|
22
|
-
worker.port.on('passbolt.clipboard.copy', async(requestId, text) => {
|
|
23
|
-
const clipboardController = new ClipboardController(worker, requestId, text);
|
|
24
|
-
await clipboardController._exec(text);
|
|
25
|
-
});
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const ClipboardEvents = {listen};
|