Skip to content

Comments

Custom Page Load Error#1

Merged
iamEvanYT merged 6 commits intomainfrom
evan/error-page
Mar 17, 2025
Merged

Custom Page Load Error#1
iamEvanYT merged 6 commits intomainfrom
evan/error-page

Conversation

@iamEvanYT
Copy link
Member

@iamEvanYT iamEvanYT commented Mar 17, 2025

Summary by CodeRabbit

  • New Features

    • Enhanced handling of custom protocol requests improves content delivery efficiency and overall user experience.
    • Introduced a dedicated error page with clear messaging, animated transitions, and options to reload or navigate back when page load issues occur.
  • Chores

    • Upgraded core dependencies to boost system stability, performance, and reliability.
    • Added new utility functions for file existence checks and content type determination.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 17, 2025

Walkthrough

This pull request implements a custom protocol handler for "flow-utility" in the Electron browser process to serve files based on URL paths, with validations and MIME type resolution. It adds error handling in tab loading by redirecting to a designated error page. New utility functions are introduced for file existence checks and content type determination. Additionally, the Browser class is now exported, dependency versions in the Electron package have been updated, and the Vite project has been enhanced with new routes and React components for a custom error page.

Changes

Files Change Summary
electron/browser/main.ts Adds a custom "flow-utility" protocol handler within app.whenReady(), validates URL paths starting with "page/", checks file existence, reads file contents, sets appropriate headers, and exports the Browser class.
electron/browser/tabs.ts Introduces a "did-fail-load" event listener on webContents to intercept load failures and redirect to an error page with constructed query parameters.
electron/browser/utils.ts New file with two exported functions: isFileExists for asynchronous file existence checking and getContentType for determining MIME type based on a file's extension.
electron/index.ts Updates import of the Browser class from a default to a named import.
electron/package.json Updates dependency versions for electron-chrome-context-menu (1.1.0), electron-chrome-extensions (4.6.5), and electron-chrome-web-store (0.10.0). Adds new dependencies mime-types and @types/mime-types.
vite/src/lib/url.ts Modifies the transformUrl function to handle error page scenarios for URLs with protocol "flow-utility:", host "page", and pathname "/error".
vite/src/routes/error/index.html
vite/src/routes/error/index.tsx
vite/src/routes/error/page.tsx
Introduces a new error page feature: an HTML file, a React entry module for initializing error rendering, and a React component that displays error details with navigation actions, styled with Tailwind CSS and motion animations.
electron/modules/flags.ts Introduces a new type definition Flags for the FLAGS object, adding ERROR_PAGE_LOAD_MODE and ensuring type safety.

Sequence Diagram(s)

sequenceDiagram
    participant App as Application
    participant PH as Protocol Handler
    participant FS as fsPromises
    participant UT as getContentType Utility

    App->>PH: Request "flow-utility://page/..."
    PH->>FS: Check file existence
    FS-->>PH: File exists? (Yes/No)
    alt File exists
        PH->>FS: Read file contents
        FS-->>PH: Return file contents
        PH->>UT: Determine MIME type
        UT-->>PH: Return MIME type
        PH->>App: Respond with file content & headers
    else File not found
        PH->>App: Return error response (404/400)
    end
Loading
sequenceDiagram
    participant Tab as Tab Component
    participant WC as WebContents
    participant ER as Error Redirect
    participant RP as React Error Page

    WC->>Tab: Trigger "did-fail-load" event
    Tab->>Tab: Validate error conditions (main frame & non-abort)
    Tab->>ER: Construct error page URL with query params
    Tab->>WC: Execute JS to update window location to error page
    ER->>RP: Load and render the error page
    RP->>RP: Display error details and provide reload/back options
Loading

Poem

I'm a rabbit hopping through the code,
With "flow-utility" leading the node.
I check each file, redirection in sight,
Making errors turn gentle and bright.
In Electron and Vite, my paws dance along,
Celebrating changes with a joyful song! 🐰
Hop on the code trail, where bugs don't belong!

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 48634d1 and 8baf45c.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • electron/browser/tabs.ts (2 hunks)
  • electron/browser/utils.ts (1 hunks)
  • electron/modules/flags.ts (1 hunks)
  • electron/package.json (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • electron/browser/utils.ts
  • electron/browser/tabs.ts
  • electron/package.json
🔇 Additional comments (1)
electron/modules/flags.ts (1)

1-13: Well-structured type definition and flag implementation!

The addition of the Flags type and the typed FLAGS object is a great improvement for type safety. The string literal union type for ERROR_PAGE_LOAD_MODE ensures only valid values can be used, and the comments clearly explain the purpose and behavior of each option. This implementation aligns well with the PR objective of implementing custom page load error handling.

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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 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.

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: 2

🧹 Nitpick comments (4)
vite/src/routes/error/index.html (1)

1-11: Clean HTML template for error page.

This is a minimal and well-structured HTML template that follows best practices:

  • Proper DOCTYPE declaration
  • Includes language attribute for accessibility
  • Sets appropriate character encoding and viewport meta tags
  • Creates a root element for mounting the React application
  • Uses module script to load the entry point

Consider adding a title element to improve accessibility and provide context in browser tabs.

  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+   <title>Error - Flow Browser</title>
  </head>
electron/browser/tabs.ts (1)

46-46: Consider removing commented code.

The commented-out line that uses loadURL instead of executeJavaScript should be either implemented or removed to maintain clean code.

-        // this.webContents.loadURL(errorPageURL.toString());
electron/browser/utils.ts (1)

12-42: Consider expanding MIME type support for future extensibility.

The getContentType function handles common file types but may need to be expanded as the application grows. Consider adding more file extensions or implementing a more scalable solution like using the mime-types package.

-export function getContentType(filePath: string) {
-  const fileExtension = path.extname(filePath).toLowerCase();
-  let contentType = "text/plain";
-
-  switch (fileExtension) {
-    case ".html":
-      contentType = "text/html";
-      break;
-    case ".js":
-      contentType = "application/javascript";
-      break;
-    case ".css":
-      contentType = "text/css";
-      break;
-    case ".json":
-      contentType = "application/json";
-      break;
-    case ".png":
-      contentType = "image/png";
-      break;
-    case ".jpg":
-    case ".jpeg":
-      contentType = "image/jpeg";
-      break;
-    case ".svg":
-      contentType = "image/svg+xml";
-      break;
-  }
-
-  return contentType;
+import mime from 'mime-types';
+
+export function getContentType(filePath: string) {
+  return mime.lookup(filePath) || 'text/plain';
+}
electron/browser/main.ts (1)

489-489: Consider making allowed directories configurable.

The FLOW_UTILITY_ALLOWED_DIRECTORIES array is hardcoded with just "error". Consider making this configurable or moving it to a constants file for better maintainability as the application grows.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fcfd5c7 and e7dc53f.

⛔ Files ignored due to path filters (2)
  • .DS_Store is excluded by !**/.DS_Store
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • electron/browser/main.ts (4 hunks)
  • electron/browser/tabs.ts (1 hunks)
  • electron/browser/utils.ts (1 hunks)
  • electron/index.ts (1 hunks)
  • electron/package.json (1 hunks)
  • vite/src/lib/url.ts (1 hunks)
  • vite/src/routes/error/index.html (1 hunks)
  • vite/src/routes/error/index.tsx (1 hunks)
  • vite/src/routes/error/page.tsx (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
vite/src/routes/error/page.tsx

[error] 99-99: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (11)
electron/index.ts (1)

1-2: Import style change looks good.

The change from default import to named import for Browser aligns with the updated export in the browser/main module. This makes the import declarations more explicit about what's being imported.

vite/src/routes/error/index.tsx (1)

1-13: Well-structured React entry point.

This is a clean implementation of a React application entry point following best practices:

  • Uses StrictMode for additional checks during development
  • Properly incorporates ThemeProvider for theme context
  • Follows the standard pattern for mounting a React app to a DOM element

The non-null assertion operator (!) on getElementById suggests you're confident the "root" element will always exist in the DOM, which is fine since it's defined in the corresponding HTML file.

electron/browser/tabs.ts (1)

35-48: Good implementation of error handling for failed page loads.

The event listener for "did-fail-load" properly redirects users to a custom error page when a page fails to load, enhancing the user experience. The implementation correctly ignores aborted operations (error code -3) which are typically user-initiated cancellations.

electron/browser/utils.ts (1)

5-10: Good implementation of async file existence check.

The isFileExists function correctly uses fsPromises with async/await pattern and properly handles errors through the Promise chain.

vite/src/routes/error/page.tsx (4)

10-53: Well-structured error information object with comprehensive coverage of common error scenarios.

The error information mapping provides user-friendly messages for various error codes, which improves the user experience significantly.


66-77: Smart handling of URL parameters in the useEffect hook.

The implementation correctly removes the "initial" parameter after first load and handles page reloading appropriately, preventing unnecessary redirects.


79-132: Excellent UI implementation with responsive design and dark mode support.

The error page UI is well-designed with responsive layouts, animation effects, and proper dark mode support, providing a good user experience across different environments.

🧰 Tools
🪛 Biome (1.9.4)

[error] 99-99: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)


97-100:

Details

✅ Verification successful

Security vulnerability with dangerouslySetInnerHTML.

Using dangerouslySetInnerHTML with content that includes URL parameters could expose users to cross-site scripting (XSS) attacks. Consider sanitizing the HTML content before rendering.

-        <div
-          className="text-gray-600 dark:text-zinc-400 mb-6 text-center"
-          dangerouslySetInnerHTML={{ __html: errorInfo.description }}
-        />
+import DOMPurify from 'dompurify';
+
+// Earlier in your component:
+const sanitizedDescription = DOMPurify.sanitize(errorInfo.description);
+
+// Then in your JSX:
+        <div
+          className="text-gray-600 dark:text-zinc-400 mb-6 text-center"
+          dangerouslySetInnerHTML={{ __html: sanitizedDescription }}
+        />

🌐 Web query:

Is DOMPurify an effective solution for preventing XSS attacks in React applications?

💡 Result:

DOMPurify is a highly effective solution for preventing XSS attacks in React applications when implemented correctly. It provides robust sanitization of HTML content by removing malicious elements while preserving safe markup, making it a critical defense layer in scenarios requiring dynamic content rendering.

Key Strengths of DOMPurify in React

  1. Whitelist-Based Sanitization
    DOMPurify uses a whitelist approach, allowing only pre-approved HTML elements and attributes (e.g., href for <a> tags) while stripping risky ones like <script> or onerror handlers[1][8]. This proactive method outperforms blacklist-based solutions.

  2. Integration with dangerouslySetInnerHTML
    React’s default escaping prevents XSS in JSX bindings but offers no protection when using dangerouslySetInnerHTML. DOMPurify fills this gap:

    import DOMPurify from 'dompurify';
    const cleanHTML = DOMPurify.sanitize(userInput);
    return <div dangerouslySetInnerHTML={{ __html: cleanHTML }} />;

    This sanitizes user-generated HTML before rendering[3][4][11].

  3. Context-Aware Filtering
    DOMPurify adapts sanitization rules based on the DOM context (e.g., HTML vs. SVG namespaces), reducing bypass risks[2][12]. For example, SVG content requires explicit configuration:

    // Explicitly set SVG namespace for proper sanitization
    DOMPurify.sanitize(dirtySVG, { NAMESPACE: 'http://www.w3.org/2000/svg' });
  4. Compatibility with Modern Frameworks
    DOMPurify works seamlessly in both client-side and server-side React environments (via jsdom)[11][14]. It also supports custom hooks for granular control over allowed elements[1][8].

Limitations and Mitigations

  • SVG/Namespace Bypass Risks
    Misconfiguring the namespace (e.g., rendering SVG without proper settings) can bypass protections. Always specify the correct NAMESPACE option[2].

  • Not a Standalone Solution
    Combine DOMPurify with:

    • Content Security Policy (CSP) to block unauthorized script execution[1][10].
    • Input Validation to reject unexpected formats (e.g., numeric-only fields)[14].
    • Linting Rules to enforce sanitization for dangerouslySetInnerHTML[3][11].

Industry Validation

  • OWASP Recommendation: DOMPurify is explicitly endorsed for HTML sanitization in the [OWASP XSS Prevention Cheat Sheet][12].
  • Adoption by Major Platforms: WordPress VIP, Signal, and others use DOMPurify to secure user-generated content[8][11].

Example Attack Mitigation

Without DOMPurify:

// Vulnerable code
<div dangerouslySetInnerHTML={{ __html: '<img src=x onerror=alert(1)>' }} />

With DOMPurify:

// Safe output: <img src="x">
const clean = DOMPurify.sanitize('<img src=x onerror=alert(1)>');
return <div dangerouslySetInnerHTML={{ __html: clean }} />;

The malicious onerror attribute is removed[8][14].

For optimal security, keep DOMPurify updated and audit configurations regularly. While no tool is 100% foolproof, DOMPurify remains the gold standard for XSS prevention in React when paired with complementary security practices[1][10][12].

Citations:


Please sanitize HTML content using DOMPurify to mitigate XSS risks.

After reviewing the security concerns and verifying via the web query, it's confirmed that DOMPurify is a highly effective solution for sanitizing HTML in React. Replace the unsanitized use of dangerouslySetInnerHTML in vite/src/routes/error/page.tsx (lines 97–100) by importing and utilizing DOMPurify to sanitize errorInfo.description. For example:

-        <div
-          className="text-gray-600 dark:text-zinc-400 mb-6 text-center"
-          dangerouslySetInnerHTML={{ __html: errorInfo.description }}
-        />
+import DOMPurify from 'dompurify';
+
+// Sanitize the HTML content before rendering
+const sanitizedDescription = DOMPurify.sanitize(errorInfo.description);
+
+        <div
+          className="text-gray-600 dark:text-zinc-400 mb-6 text-center"
+          dangerouslySetInnerHTML={{ __html: sanitizedDescription }}
+        />

Be sure to keep DOMPurify updated and review its configuration if any specialized content (like SVG) is rendered. This change significantly improves the protection against potential XSS attacks.

🧰 Tools
🪛 Biome (1.9.4)

[error] 99-99: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

electron/browser/main.ts (2)

147-147: Good addition of export to the Browser class.

Making the Browser class exportable improves modularity and allows it to be used in other parts of the application.


488-549: Well-implemented protocol handler for custom file serving.

The protocol handler for "flow-utility" is well-structured with:

  • Proper path validation and sanitization
  • Directory access restrictions
  • Appropriate error handling
  • Content type detection for served files
  • Smart handling of directory requests with index.html resolution
electron/package.json (1)

16-18: Pinned Dependency Versions for Stability.
The updated dependency entries now explicitly require fixed versions, which is excellent for ensuring reproducible builds and minimizing surprises from upstream changes. Please verify these version updates are fully compatible with the rest of your Electron setup, particularly with the new protocol handler enhancements.

@iamEvanYT iamEvanYT merged commit 5edd3f8 into main Mar 17, 2025
1 check passed
@iamEvanYT iamEvanYT deleted the evan/error-page branch March 17, 2025 21:31
This was referenced Mar 21, 2025
@coderabbitai coderabbitai bot mentioned this pull request Mar 29, 2025
4 tasks
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