Skip to content

Conversation

@iamEvanYT
Copy link
Member

@iamEvanYT iamEvanYT commented May 17, 2025

tldr

This resolves the problem where webRequests intercept handlers replace each other.

Summary by CodeRabbit

  • New Features
    • Introduced advanced web request handling with multiple, filterable listeners for request lifecycle events.
    • Added URL pattern matching supporting wildcards and special schemes.
  • Improvements
    • Enhanced session objects for content blocking with isolated blocking capabilities.
    • Expanded debug options with new areas for web requests and pattern matching.
  • Bug Fixes
    • Improved log file output by removing color codes while retaining console formatting.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 17, 2025

Walkthrough

A new URL pattern-matching utility and an advanced web request handling abstraction are introduced, enhancing session and web request management. Content blocking now utilizes the improved session wrapper. Logging is refined to separate colored console output from decolored log file entries. Debugging areas are expanded with new categories.

Changes

File(s) Change Summary
src/main/browser/utility/match-pattern.ts Added a matchPattern function for matching URLs against WebExtension-style patterns, supporting schemes, hosts, paths, and wildcards.
src/main/browser/utility/web-requests.ts Introduced a UnifiedWebRequest class and related helpers for multi-listener, filterable, and asynchronous web request event management, plus session and web request enhancement functions.
src/main/modules/content-blocker.ts Updated to use createBetterSession with a constant key when enabling/disabling content blocking, wrapping sessions for enhanced handling.
src/main/modules/logs.ts Adjusted logging to write decolored (ANSI-stripped) output to log files while preserving colored output for the console.
src/main/modules/output.ts Extended DEBUG_AREAS with new areas: WEB_REQUESTS_INTERCEPTION, WEB_REQUESTS, and MATCH_PATTERN.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant UnifiedWebRequest
    participant WebRequest
    participant Listener

    Caller->>UnifiedWebRequest: onBeforeRequest(filter, listener, id)
    UnifiedWebRequest->>WebRequest: Registers internal handler
    WebRequest-->>UnifiedWebRequest: Emits event
    UnifiedWebRequest->>Listener: Calls all matching listeners
    Listener-->>UnifiedWebRequest: Returns (possibly async) result
    UnifiedWebRequest-->>WebRequest: Aggregates and applies results
Loading
sequenceDiagram
    participant ContentBlocker
    participant Session
    participant createBetterSession
    participant Blocker

    ContentBlocker->>createBetterSession: Wrap session with key
    createBetterSession-->>ContentBlocker: Returns enhanced session
    ContentBlocker->>Blocker: enableBlockingInSession(enhanced session)
Loading

Poem

The bunny hops with code anew,
Matching URLs, filtering through—
Web requests unified, sessions enhanced,
Log files clean while colors danced.
Debugging grows with extra care,
Content blocked with wrappers rare.
🐇✨

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


Note

⚡️ Faster reviews with caching

CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.
Enjoy the performance boost—your workflow just got faster.

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link
Contributor

github-actions bot commented May 17, 2025

Build artifacts for all platforms are ready! 🚀

Download the artifacts from:

(execution 15087859807 / attempt 1)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (3)
src/main/browser/utility/match-pattern.ts (2)

59-69: Consider optimizing regex pattern creation for frequently used patterns.

The path matching logic converts the path pattern to a regex string and creates a new RegExp object for each match operation. If this function is called frequently with the same patterns, consider caching the compiled regex patterns to improve performance.

// Add at the top of the file:
+const pathPatternCache = new Map<string, RegExp>();

// Then modify the path regex creation:
-const pathRegexStr = pathPattern.replace(/\*/g, ".*").replace(/\?/g, "\\?");
-const pathRegex = new RegExp(`^${pathRegexStr}$`);

+// Get or create the path regex
+let pathRegex = pathPatternCache.get(pathPattern);
+if (!pathRegex) {
+  const pathRegexStr = pathPattern.replace(/\*/g, ".*").replace(/\?/g, "\\?");
+  pathRegex = new RegExp(`^${pathRegexStr}$`);
+  pathPatternCache.set(pathPattern, pathRegex);
+}

70-73: Appropriate error handling with debug logging.

The function properly catches any errors that might occur during URL parsing or pattern matching and logs them to the debug output. Using WEB_REQUESTS as the debug area here is fine, but consider using MATCH_PATTERN for consistency with the rest of the file.

-debugPrint("WEB_REQUESTS", `Error matching URL pattern: ${error}`);
+debugPrint("MATCH_PATTERN", `Error matching URL pattern: ${error}`);
src/main/browser/utility/web-requests.ts (1)

658-667: Cache implemented with a strong Map → memory leak risk

betterWebRequestCache keys are plain strings that reference the ID + underlying objectId.
Once an enhanced instance is created there is no path for GC even if the original WebRequest is long-gone.

Switch to a two-level WeakMap keyed by the original WebRequest (or Session) so the cache is eligible for collection automatically:

-// Cache for betterWebRequest instances
-const betterWebRequestCache = new Map<string, WebRequest>();
+// GC-friendly cache
+const betterWebRequestCache = new WeakMap<WebRequest, Map<string, WebRequest>>();

(You will need small adjustments when storing/retrieving but the change prevents unbounded growth during long-running app sessions.)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between c753eec and 768f8e1.

📒 Files selected for processing (5)
  • src/main/browser/utility/match-pattern.ts (1 hunks)
  • src/main/browser/utility/web-requests.ts (1 hunks)
  • src/main/modules/content-blocker.ts (4 hunks)
  • src/main/modules/logs.ts (1 hunks)
  • src/main/modules/output.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/main/modules/content-blocker.ts (1)
src/main/browser/utility/web-requests.ts (1)
  • createBetterSession (771-809)
src/main/browser/utility/match-pattern.ts (1)
src/main/modules/output.ts (1)
  • debugPrint (28-34)
🪛 Biome (1.9.4)
src/main/modules/logs.ts

[error] 42-42: Unexpected control character in a regular expression.

Control characters are unusual and potentially incorrect inputs, so they are disallowed.

(lint/suspicious/noControlCharactersInRegex)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (ubuntu-latest)
  • GitHub Check: build (windows-latest)
🔇 Additional comments (12)
src/main/modules/output.ts (1)

20-23: Good addition of debug areas for the new web request features.

The new debug areas clearly map to the new functionalities being added in this PR. I notice that WEB_REQUESTS is set to true by default, while others are false, which makes sense to provide visibility into the core web request operations while keeping the more detailed debug areas disabled by default.

src/main/modules/logs.ts (2)

38-45: Good improvement to log file handling.

This change properly separates the console output from log file content by creating a separate decoloredChunk variable. Now the console output retains the original ANSI color codes, while the log file receives the cleaned version without these codes.

🧰 Tools
🪛 Biome (1.9.4)

[error] 42-42: Unexpected control character in a regular expression.

Control characters are unusual and potentially incorrect inputs, so they are disallowed.

(lint/suspicious/noControlCharactersInRegex)


42-42: The control character use in regex is intentional and properly commented.

The static analysis tool flags the control character in the regex, but this is expected since we're specifically detecting ANSI escape codes. The eslint-disable comment properly documents this intentional use.

🧰 Tools
🪛 Biome (1.9.4)

[error] 42-42: Unexpected control character in a regular expression.

Control characters are unusual and potentially incorrect inputs, so they are disallowed.

(lint/suspicious/noControlCharactersInRegex)

src/main/modules/content-blocker.ts (4)

1-1: Good integration with the new unified web requests module.

The import of createBetterSession from the new web requests utility is appropriate for the goal of this PR.


10-10: Clear and descriptive session key.

Using a constant with a descriptive name SESSION_KEY makes the code more maintainable and helps identify which component is using the session wrapper.


63-63: Good implementation of enhanced session handling.

Wrapping the session with createBetterSession when disabling the blocker ensures that the correct web request handler is accessed.


85-85: Consistent use of enhanced sessions.

The implementation consistently uses the enhanced session wrapper for both enabling and disabling the blocker, which ensures proper web request handling.

src/main/browser/utility/match-pattern.ts (5)

3-10: Good documentation of the match pattern format.

The documentation clearly explains the format and includes a reference to the Mozilla documentation, which is helpful for maintainers.


13-21: Comprehensive handling of the special <all_urls> pattern.

The implementation correctly handles the special pattern and checks for supported schemes. The try-catch block properly handles potential URL parsing errors.


24-30: Well-structured pattern validation.

The regex pattern for validating match patterns is comprehensive and handles the various components correctly. The debug print for invalid patterns is helpful for troubleshooting.


35-44: Thorough scheme matching logic.

The scheme matching logic correctly handles both wildcard schemes and specific schemes, with appropriate protocol normalization.


46-57: Comprehensive host matching implementation.

The host matching correctly handles wildcards, specific hostnames, and subdomain patterns with the *. syntax. The check on line 52 ensures that the hostname isn't exactly the suffix, which is the correct behavior for subdomain matching.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (3)
src/main/browser/utility/web-requests.ts (3)

685-770: betterWebRequest drops any future WebRequest members

This manual wrapper lists only the known event methods. If Electron adds a new
method in a minor release, client code will suddenly receive undefined. A
proxy that forwards unknown properties to unifiedWebRequest (or the original
webRequest) future-proofs the API without maintenance overhead — exactly the
approach already used for the session proxy below.

This mirrors a previous remark; consider it a friendly reminder.


190-197: ⚠️ Potential issue

Request-header mutation discards multi-value headers and prior edits

The new newRequestHeaders object is rebuilt from scratch and forces every
value to a single string (Array.isArray(value) ? value[0] : value).
This:

  1. Loses legitimate multi-value headers such as Set-Cookie or Accept.
  2. Obliterates modifications done by earlier listeners in the chain.

Consider merging instead of replacing and keep the full union
string | string[] type:

-          const newRequestHeaders: Record<string, string> = {};
-          for (const [key, value] of Object.entries(response.requestHeaders)) {
-            newRequestHeaders[key] = Array.isArray(value) ? value[0] : value;
-          }
-
-          currentRequestHeaders = newRequestHeaders;
+          currentRequestHeaders = {
+            ...currentRequestHeaders,
+            ...(response.requestHeaders ?? {})
+          };

Do the same for response headers below.


122-156: 🛠️ Refactor suggestion

Add a timeout (or fail-safe) to prevent requests from hanging indefinitely

Promise.all(promises) waits forever if any listener forgets/decides not to
call its fakeCallback. In that situation the network request is never
released and the tab can freeze.

A minimal mitigation is to race Promise.all against a short timeout
(e.g. 200-300 ms, matching Electron’s own defaults) and fall back to
callback({}) when the timeout fires. Re-use the same helper for
onBeforeSendHeaders and onHeadersReceived, which have identical risk.

-      Promise.all(promises).then((responses) => {
+      const TIMEOUT_MS = 250;
+      Promise.race([
+        Promise.all(promises),
+        new Promise<CallbackResponse[]>(res =>
+          setTimeout(() => res([]), TIMEOUT_MS)
+        )
+      ]).then((responses) => {

This removes the single-point-of-failure while still honouring fast listeners.

🧹 Nitpick comments (1)
src/main/browser/utility/web-requests.ts (1)

656-669: Caches grow unbounded – potential memory leak

betterWebRequestCache / betterSessionCache are ordinary Maps keyed by
(composite) IDs and are never cleaned up. Long-lived apps that create many
temporary sessions (e.g. incognito windows) will keep every wrapper alive.

If eviction by design is hard, at least switch to WeakMap keyed by the
original object so wrappers are GC-eligible once the underlying
WebRequest/Session is gone.

-const betterWebRequestCache = new Map<string, WebRequest>();
+const betterWebRequestCache = new WeakMap<object, WebRequest>();

…and generate the cache key from the wrapper target instead of a string.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 768f8e1 and 280ce87.

📒 Files selected for processing (1)
  • src/main/browser/utility/web-requests.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: build (ubuntu-latest)
  • GitHub Check: build (windows-latest)
  • GitHub Check: build (macos-latest)

@iamEvanYT iamEvanYT merged commit 8f7b888 into main May 17, 2025
8 checks passed
@iamEvanYT iamEvanYT deleted the evan/unified-web-requests branch May 17, 2025 18:28
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.

2 participants