Skip to content

Make download directory configurable#145

Merged
esokullu merged 5 commits into
mainfrom
agent/configurable-download-directory
Jul 17, 2026
Merged

Make download directory configurable#145
esokullu merged 5 commits into
mainfrom
agent/configurable-download-directory

Conversation

@esokullu

Copy link
Copy Markdown
Owner

Summary

  • add a configurable download subdirectory under Settings > General for Chrome and Firefox
  • keep the field empty by default so downloads continue using the browser and operating system default
  • validate portable relative paths and include the preference in config export/import
  • route Chrome downloads centrally and Firefox downloads through its supported downloads.download({ filename }) call sites
  • add localized settings copy and focused regression coverage

Why

Users currently cannot choose where WebBrain-created downloads are grouped. This adds an optional relative subdirectory without overriding the browser or operating system download root.

Firefox does not expose Chrome's filename-determination event, so its implementation applies the configured path before each download call instead of exposing a setting that would have no effect.

Impact

Existing behavior is unchanged unless a user enters a relative subdirectory. Clearing the setting restores the system default behavior.

Validation

  • npm test — 884/884 unit tests passed
  • security corpus — 60/60 checks passed
  • git diff --check

@esokullu

Copy link
Copy Markdown
Owner Author

@codex pls review

@webbrain-one
webbrain-one marked this pull request as ready for review July 17, 2026 06:18

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c51b1d2cb6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/firefox/src/download-directory.js Outdated
const stored = await api.storage.local.get(DOWNLOAD_DIRECTORY_STORAGE_KEY);
const directory = normalizeDownloadDirectory(stored?.[DOWNLOAD_DIRECTORY_STORAGE_KEY]);
if (!directory) return original;
const candidate = original || filenameFromDownloadUrl(url) || 'download';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve server-selected filenames when routing Firefox downloads

When a Firefox user has downloadDirectory set and a download call does not supply an explicit filename, this line always fabricates one from the URL or download. For download_files/download_resource_from_page URLs such as /export?id=1 that rely on Content-Disposition for the real name and extension, passing this filename to browser.downloads.download bypasses Firefox's normal filename selection and saves files as Work/WebBrain/export or Work/WebBrain/download instead of the server-provided filename.

Useful? React with 👍 / 👎.

@esokullu

Copy link
Copy Markdown
Owner Author

@codex pls review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 15472fc13a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +2219 to +2220
const suggestedFilename = (i === 0 ? singleFilename : null)
|| await discoverHttpDownloadFilename(url);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid probing filenames when no directory is configured

In Firefox's download_files path, when the new setting is blank, filenameInConfiguredDownloadDirectory() returns suggestedFilename unchanged, so this line now performs a credentialed HEAD request and then sets opts.filename even though the user did not configure a subdirectory. For endpoints such as /export?id=... where HEAD omits Content-Disposition but GET supplies it, this overrides the browser's server-selected filename with the URL basename, and one-shot/signed URLs also see an extra request. Only discover and supply a filename when a configured directory actually needs a basename, or when the user supplied args.filename.

Useful? React with 👍 / 👎.

@esokullu

Copy link
Copy Markdown
Owner Author

@codex pls review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4e964d5350

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +466 to +467
return filenameFromContentDisposition(response.headers?.get?.('content-disposition'))
|| filenameFromHttpUrl(responseUrl);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid overriding GET-selected filenames

When a configured download directory is set, a URL whose HEAD request succeeds without Content-Disposition falls back to filenameFromHttpUrl(responseUrl) and then passes that path to downloads.download. In that case Firefox no longer gets to choose the filename from the actual GET response, so endpoints that only send Content-Disposition on GET (or otherwise pick a better filename during the real download) are saved under a generic URL basename such as WebBrain/download; leave filename undefined unless a real filename was supplied or discovered from the response headers.

Useful? React with 👍 / 👎.

@esokullu

Copy link
Copy Markdown
Owner Author

@codex pls review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2ae8546a27

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +440 to +442
const response = await fetch(target, {
method: 'HEAD',
credentials: 'include',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid probing one-time URLs before downloading

When a Firefox user has a download directory configured, URLs without an explicit filename now make this authenticated HEAD request before the real browser.downloads.download call. For signed export/download links that are valid for a single request or mark the token used on first access, this probe can consume the URL and make the subsequent GET fail even though the same download worked before the directory setting was enabled.

Useful? React with 👍 / 👎.

Comment thread src/firefox/src/download-directory.js Outdated
Comment on lines +23 to +28
const basename = String(filename ?? '')
.replace(/\\/g, '/')
.split('/')
.pop()
.replace(/[\u0000-\u001f\u007f]/g, '')
.trim();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Sanitize suggested basenames before downloads.download

With a configured Firefox download directory, server-provided Content-Disposition names are passed through this helper and then supplied as an explicit downloads.download({ filename }); unlike the browser’s normal filename choice, the WebExtension API rejects explicit filenames containing characters such as :, ?, quotes, or leading dots. A common header like filename="Q1: report.pdf" therefore makes the download fail only when the directory setting is enabled, instead of letting Firefox sanitize the suggested basename.

Useful? React with 👍 / 👎.

@esokullu

Copy link
Copy Markdown
Owner Author

@codex pls review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: 5ff2dcf7fb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@esokullu
esokullu merged commit 7210c19 into main Jul 17, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant