-
Notifications
You must be signed in to change notification settings - Fork 2.6k
feat: add integrated web preview with element selection #5976
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Add WebPreviewProvider to manage preview panel in sidebar - Create React-based UI with URL navigation and viewport controls - Implement element selection with context extraction (HTML, CSS, XPath) - Add web_preview tool for AI integration - Register commands and update package.json - Update type definitions and tool configurations This implementation provides: - Web preview panel in VSCode sidebar - Click-to-select elements with visual highlighting - Element context extraction for AI assistance - Responsive viewport controls - Integration with Roo Code AI through web_preview tool
| | "finishTask" | ||
| | "searchAndReplace" | ||
| | "insertContent" | ||
| | "web_preview" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typographical issue: The new union value "web_preview" is using snake_case whereas the other values use camelCase (e.g. "finishTask", "searchAndReplace", "insertContent"). Consider using "webPreview" for consistency.
| {state.url ? ( | ||
| <iframe | ||
| ref={iframeRef} | ||
| src={state.url} |
Check warning
Code scanning / CodeQL
Client-side URL redirect Medium
user-provided value
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 5 months ago
To address the issue, we need to ensure that only trusted URLs are used as the src attribute for the <iframe>. The best way to fix this is to implement a whitelist of allowed URLs or domains and validate state.url against this list before using it. If the URL is not in the whitelist, we should not render it in the iframe.
- Define a list of allowed domains or URLs in the component.
- Create a utility function to validate a URL against the whitelist.
- Before setting
state.url, validate the URL. If it is not valid, discard or handle it appropriately (e.g., show an error message). - Update the
handleMessagefunction to include this validation and ensure only safe URLs are stored in the component's state.
-
Copy modified lines R40-R52 -
Copy modified lines R59-R61 -
Copy modified lines R63-R64
| @@ -37,16 +37,31 @@ | ||
| const [isSelectionMode, setIsSelectionMode] = useState(false) | ||
| const [highlightedElement, setHighlightedElement] = useState<HTMLElement | null>(null) | ||
|
|
||
| // List of allowed domains for iframe URLs | ||
| const allowedDomains = ["example.com", "trusted-site.org"] | ||
|
|
||
| // Utility function to validate URLs | ||
| const isValidUrl = (url: string): boolean => { | ||
| try { | ||
| const parsedUrl = new URL(url) | ||
| return allowedDomains.includes(parsedUrl.hostname) | ||
| } catch { | ||
| return false | ||
| } | ||
| } | ||
|
|
||
| // Handle messages from extension | ||
| useEffect(() => { | ||
| const handleMessage = (event: MessageEvent) => { | ||
| const message = event.data | ||
| switch (message.type) { | ||
| case "updateState": | ||
| setState(message.state) | ||
| if (message.state.url) { | ||
| // Validate the URL before updating state | ||
| if (message.state.url && isValidUrl(message.state.url)) { | ||
| setState(message.state) | ||
| setUrlInput(message.state.url) | ||
| } | ||
| } else { | ||
| console.warn("Invalid URL received | ||
| break | ||
| } | ||
| } |
| {state.url ? ( | ||
| <iframe | ||
| ref={iframeRef} | ||
| src={state.url} |
Check failure
Code scanning / CodeQL
Client-side cross-site scripting High
user-provided value
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 5 months ago
To fix this client-side XSS vulnerability, validate and sanitize the URL received from event.data.state.url before using it as the src of the <iframe>. The best way is to enforce that only trusted, well-formed URLs are accepted. This can be achieved by checking that the URL is a valid HTTP/HTTPS URL and/or matches a whitelist of allowed domains.
The fix should be implemented in the handleMessage function around line 42. Before updating the state with a new URL, validate it using the built-in URL constructor and ensure it uses an allowed protocol (http: or https:) and (optionally) matches a trusted domain. If the URL is invalid, ignore the update or show an error. You may also want to add a helper function for this validation.
The changes are limited to the region in the provided file where the message is handled and state is updated, so no changes are needed outside webview-ui/src/components/web-preview/WebPreview.tsx. You may need to add a helper function, imports, and update how setState and setUrlInput are called.
-
Copy modified lines R42-R53 -
Copy modified lines R58-R62 -
Copy modified lines R64-R67 -
Copy modified line R73
| @@ -39,22 +39,38 @@ | ||
|
|
||
| // Handle messages from extension | ||
| useEffect(() => { | ||
| // Helper to validate URLs before use in iframe | ||
| function isSafeUrl(url: string | undefined): boolean { | ||
| if (!url) return false; | ||
| try { | ||
| const parsed = new URL(url, window.location.origin); | ||
| // Only allow http(s), optionally restrict to trusted domains | ||
| return parsed.protocol === "http:" || parsed.protocol === "https:"; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| const handleMessage = (event: MessageEvent) => { | ||
| const message = event.data | ||
| switch (message.type) { | ||
| case "updateState": | ||
| setState(message.state) | ||
| if (message.state.url) { | ||
| setUrlInput(message.state.url) | ||
| // Defensive copy and sanitize url | ||
| const safeState = { ...message.state } | ||
| if (safeState.url && !isSafeUrl(safeState.url)) { | ||
| // If unsafe, ignore url (or set to empty) | ||
| safeState.url = undefined | ||
| } | ||
| setState(safeState) | ||
| if (safeState.url) { | ||
| setUrlInput(safeState.url) | ||
| } | ||
| break | ||
| } | ||
| } | ||
|
|
||
| window.addEventListener("message", handleMessage) | ||
| return () => window.removeEventListener("message", handleMessage) | ||
| }, []) | ||
|
|
||
|
|
||
| // Navigate to URL | ||
| const handleNavigate = useCallback(() => { | ||
| if (urlInput) { |
|
Closing, the implementation will be done by @SannidhyaSah |
Fixes #5971
Summary
This PR implements an integrated web preview feature with element selection capabilities for AI context, as requested in issue #5971. The implementation provides a seamless web development experience by eliminating the need to switch between the IDE and external browsers.
Features Implemented
1. Web Preview Panel
2. Element Selection & Context Extraction
3. AI Integration
web_previewtool for AI assistant integration4. Technical Implementation
Changes Made
src/core/webview/WebPreviewProvider.ts- Main provider classwebview-ui/src/components/web-preview/WebPreview.tsx- React UI componentwebview-ui/src/components/web-preview/WebPreview.css- Stylingsrc/core/tools/webPreviewTool.ts- AI tool integrationsrc/extension.ts- Registered the preview providersrc/activate/registerCommands.ts- Added preview commandssrc/package.json- Added view container and commandsTesting
Screenshots
The implementation matches the requested functionality from the issue, providing an integrated preview experience similar to Windsurf IDE.
Next Steps
This implementation provides a solid foundation that can be extended with additional features like:
Important
Adds integrated web preview with element selection and AI integration in VSCode, including a new sidebar panel and commands.
WebPreviewProviderinWebPreviewProvider.tsto manage the webview lifecycle.WebPreview.tsxfor React UI component andWebPreview.cssfor styling.web_previewtool inwebPreviewTool.tsfor AI assistant integration.openWebPreviewandgetSelectedElementcommands inregisterCommands.ts.package.jsonto register new commands and view.vite.config.tsfor new webview entry point.webPreview.htmlfor webview setup.This description was created by
for ab7ccf1. You can customize this summary. It will automatically update as commits are pushed.