Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ module.exports = function (grunt) {
grunt.registerTask('build-chromium-mv3-prod', ['clean:build', 'pre-dist', 'copy:config_default', 'bundle-chromium-mv3', 'shell:build_service_worker_prod', 'shell:build_content_script_prod', 'shell:build_web_accessible_resources_prod', 'shell:build_chromium_mv3_prod']);

grunt.registerTask('build-safari', ['build-safari-debug', 'build-safari-prod']);
grunt.registerTask('build-safari-debug', ['clean:build', 'pre-dist', 'copy:config_debug', 'bundle-safari', 'shell:build_service_worker_debug', 'shell:build_content_script_debug', 'shell:build_web_accessible_resources_debug']);
grunt.registerTask('build-safari-prod', ['clean:build', 'pre-dist', 'copy:config_default', 'bundle-safari', 'shell:build_service_worker_prod', 'shell:build_content_script_prod', 'shell:build_web_accessible_resources_prod']);
grunt.registerTask('build-safari-debug', ['clean:build', 'pre-dist', 'copy:config_debug', 'bundle-safari', 'shell:build_service_worker_debug', 'shell:build_content_script_debug', 'shell:build_web_accessible_resources_debug', 'shell:build_safari_debug']);
grunt.registerTask('build-safari-prod', ['clean:build', 'pre-dist', 'copy:config_default', 'bundle-safari', 'shell:build_service_worker_prod', 'shell:build_content_script_prod', 'shell:build_web_accessible_resources_prod', 'shell:build_safari_prod']);

grunt.registerTask('externalize-locale-strings', ['shell:externalize']);

Expand Down Expand Up @@ -455,6 +455,31 @@ module.exports = function (grunt) {
'./node_modules/.bin/crx pack ' + path.build + ' -p key.pem -o ' + path.dist_chromium_mv3 + 'passbolt-' + pkg.version + '.crx ',
"echo '\nZip and Crx files generated in " + path.dist_chromium_mv3 + "'"
].join(' && ')
},

/**
* Safari
* The Xcode wrapper app can be generated separately via `safari-web-extension-converter`.
*/
build_safari_debug: {
options: {
stderr: false
},
command: [
'mkdir -p ' + path.dist_safari,
'zip -q -1 -r ' + path.dist_safari + 'passbolt-' + pkg.version + '-debug.zip ' + path.build,
"echo '\nZip generated in " + path.dist_safari + "'"
].join(' && ')
},
build_safari_prod: {
options: {
stderr: false
},
command: [
'mkdir -p ' + path.dist_safari,
'zip -q -1 -r ' + path.dist_safari + 'passbolt-' + pkg.version + '.zip ' + path.build,
"echo '\nZip generated in " + path.dist_safari + "'"
].join(' && ')
}
}
});
Expand Down
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,33 @@ grunt build
```
The build can be found under ```dist/chromium-mv3``` or ```dist/chromium-mv2``` or ```dist/firefox```.

## Safari

The repository includes a Safari (MV3) manifest at `src/safari/manifest.json`.

### Build the Safari WebExtension bundle (zip)

This produces a zip suitable for local testing or as an input to Apple's converter:

```sh
npm ci
npm run build:safari
```

Artifacts:
- `build/all/` (the bundled extension sources)
- `dist/safari/passbolt-<version>.zip`

### Generate the Xcode project (optional)

On macOS with Xcode installed:

```sh
npm run dev:safari:convert
```

This generates `./build-safari-extension/` (ignored by git).

## Updating the vendors or the styleguide

You can update the vendors or the styleguide in the ```package.json``` and run the copy task
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@
},
"scripts": {
"build": "npx grunt build",
"build:safari": "grunt build-safari-prod",
"build:safari:debug": "grunt build-safari-debug",
"build:background-page": "webpack --config webpack.background-page.config.js",
"build:service-worker": "webpack --config webpack.service-worker.config.js; webpack --config webpack-offscreens.config.js",
"build:content-scripts": "npm run build:content-scripts:app; npm run build:content-scripts:browser-integration; npm run build:content-scripts:public-website",
Expand All @@ -110,7 +112,7 @@
"dev:build:web-accessible-resources:app": "webpack --env debug=true --config webpack-data.config.js; webpack --env debug=true --config webpack-data.download.config.js",
"dev:build:web-accessible-resources:browser-integration": "webpack --env debug=true --config webpack-data.in-form-call-to-action.config.js; webpack --env debug=true --config webpack-data.in-form-menu.config.js",
"dev:safari:build": "grunt build-safari-debug; npm run dev:safari:convert",
"dev:safari:convert": "xcrun safari-web-extension-converter --app-name Passbolt-Safari-Extension --swift --macos-only --project-location ./build-safari-extension --bundle-identifier com.passbolt.safari-extension --force --no-open build/all/",
"dev:safari:convert": "xcrun safari-web-extension-converter --app-name Passbolt-Safari-Extension --swift --macos-only --project-location ./build-safari-extension --bundle-identifier com.passbolt.safari-extension --force --no-open --no-prompt --copy-resources build/all/",
"dev:watch:build:background-page": "npm run dev:build:background-page -- -w",
"dev:watch:build:service-worker": "npm run dev:build:service-worker -- -w",
"dev:watch:build:content-scripts:app": "npm run dev:build:content-scripts:app -- -w",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ describe("GroupsCollection", () => {
const collection = new GroupsCollection(groupsDtos, { ignoreInvalidEntity: true });
const time = performance.now() - start;
expect(collection).toHaveLength(groupsCount);
expect(time).toBeLessThan(5_000);
const limitMs = process.env.CI ? 5_000 : 10_000;
expect(time).toBeLessThan(limitMs);
});
});

Expand Down
24 changes: 21 additions & 3 deletions src/all/background_page/utils/format/formDataUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ import Base64Utils from "./base64";
* The class that deals with Passbolt to convert formData.
*/
class FormDataUtils {
/**
* Check if a value looks like a Blob/File across realms (jsdom vs undici vs browser).
* We avoid `instanceof` because it breaks when FormData/File come from different globals.
* @param {*} value
* @return {boolean}
*/
static isBlobLike(value) {
return !!value
&& typeof value === "object"
&& typeof value.arrayBuffer === "function"
&& typeof value.type === "string"
&& typeof value.size === "number";
}

/**
* Transform a form data to an array of object
* @param {FormData} formData The form data
Expand All @@ -29,10 +43,14 @@ class FormDataUtils {
const formDataObject = {
key: key,
};
// BLOB in FormData is transformed into a File
if (value instanceof File) {
// BLOBs in FormData are typically returned as File objects, but the constructor can
// differ across environments (browser vs jsdom vs Node/undici).
if (FormDataUtils.isBlobLike(value)) {
formDataObject.value = await Base64Utils.blobToBase64(value);
formDataObject.name = value.name;
// `name` is only present on File, not Blob. Keep it optional.
if (typeof value.name === "string") {
formDataObject.name = value.name;
}
formDataObject.type = FormDataUtils.TYPE_FILE;
} else {
formDataObject.value = value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ export const formDataString = () => {

export const formDataFile = () => {
const formDataBody = new FormData();
const file1 = new File(["test"], "file 1", { type: "image/png" });
const file2 = new File(["test"], "file 2", { type: "image/png" });
// Use Blob + filename to avoid File/FormData realm mismatches (jsdom vs Node/undici).
const file1 = new Blob(["test"], { type: "text/plain" });
const file2 = new Blob(["test"], { type: "text/plain" });
formDataBody.append("file", file1, "file 1");
formDataBody.append("file", file2, "file 2");
return formDataBody;
Expand Down