Skip to content

Handle links with href='blob:..' in WebViews and Notebook #98101

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

Closed
DonJayamanne opened this issue May 18, 2020 · 12 comments · Fixed by #98690
Closed

Handle links with href='blob:..' in WebViews and Notebook #98101

DonJayamanne opened this issue May 18, 2020 · 12 comments · Fixed by #98690
Assignees
Labels
bug Issue identified by VS Code Team member as probable bug notebook verified Verification succeeded
Milestone

Comments

@DonJayamanne
Copy link
Contributor

Python Notebook implementation has special code to handle click events of links containing an ObjectUrl (href=blob:....).

I'm hoping VS Code would handle this natively as these links allow users to save blobs as files. This is generic enough that it need not be something special to the Python implementation. Would benefit anyone using the new VSC API to display HTML that allows saving images.

Current Python Notebook implementation:

  • We handle all click events in document
  • If target element === a and starts with blob:.
    • Then we get the blob contents and send it to extension
    • On extension side we prompt user to save the file using showSaveDialog.

@rebornix /cc

@kieferrm
Copy link
Member

@DonJayamanne what is the use case for this?

@DonJayamanne
Copy link
Contributor Author

DonJayamanne commented May 20, 2020

Sure, a user could render a plotly plot and such plots can contain links to save images, and those hrefs have a ref to object urls.
This isn't specific to Python extension, any HTML could have markup that allows users to save images <a href="blob://" download>.
Also, opening such a plot in other notebook viewer, user is able to click such links and save the images.

If this isn't address, then VSCode displays an empty page in notebook with an error message (see below). I think this is due to the fact that href results in nativigating the current page to url=blob://.

& again, we can address this with a custom renderer, however I believe this is generic enough for VSC to handle.

Screen Shot 2020-05-14 at 12 37 23
Screen Shot 2020-05-14 at 12 37 30

@rebornix rebornix added the bug Issue identified by VS Code Team member as probable bug label May 25, 2020
@rebornix rebornix added this to the May 2020 milestone May 25, 2020
@roblourens
Copy link
Member

TIL about the URL.createObjectURL API. Should this also work for data: URLs?

@DonJayamanne
Copy link
Contributor Author

DonJayamanne commented May 26, 2020

Should this also work for data: URLs?

Good pick. I would say yes.
At the end of the day someone could render a link with a download attribute <a download href="data:.....">

@roblourens
Copy link
Member

To do this for blob ULIs, I have to download the contents of the URL in the context of the webview, and pipe it back to vscode to write to a file.

Data URLs are easier, I can just open it in a browser. Maybe an experience in vscode would be nicer though.

Where are these urls coming from in your case, some 3rd party renderer code or your extension code?

@DonJayamanne
Copy link
Contributor Author

DonJayamanne commented May 27, 2020

some 3rd party renderer code or your extension code?

3rd party

have to download the contents of the URL in the context of the webview, and pipe it back to vscode to write to a file.

That's exactly what we have in our python extension when using the webview. I thought this would be generic enough for VSCode to handle, as others could end up with similar scenarios, at the end of the day it's from a 3rd party package.

@roblourens
Copy link
Member

Yeah, I think it makes sense for us to handle this as well.

@roblourens
Copy link
Member

Do you have an example of a notebook that has this button? Is this from ipywidgets?

@roblourens
Copy link
Member

Also can you link me to the code that handles this in your extension?

@DonJayamanne
Copy link
Contributor Author

DonJayamanne commented May 27, 2020

https://github.com/microsoft/vscode-python/blob/e8449952b11835c04f960ddbda17f27e17ac9e5d/src/datascience-ui/interactive-common/handlers.ts#L28-L45

            // We an have an image (as a blob) and the reference is blob://null:<someguid>
            // We need to get the blob, for that make a http request and the response will be the Blob
            // Next convert the blob into something that can be sent to the client side.
            // Just send an inlined base64 image to `linkClick`, such as `data:image/png;base64,xxxxx`
            const xhr = new XMLHttpRequest();
            xhr.open('GET', anchor.href, true);
            xhr.responseType = 'blob';
            xhr.onload = () => {
                const blob = xhr.response;
                const reader = new FileReader();
                reader.readAsDataURL(blob);
                reader.onload = () => {
                    if (typeof reader.result === 'string') {
                        linkClick(reader.result);
                    }
                };
            };
            xhr.send();

Do you have an example of a notebook that has this button? Is this from ipywidgets?

No, its plot generated by plotly.
Here's the code required to generate such a plot:

import plotly.graph_objects as go
fig = go.Figure(
    data=[go.Bar(y=[2, 1, 3])],
    layout_title_text="A Figure Displayed with fig.show()"
)

fig.show()
import plotly

plotly.ipynb.txt

@roblourens
Copy link
Member

I thought this was working on Wednesday, but now I get a CORS error when I fetch any blob URL from the webview code. Did you do anything to handle this? I don't understand why it's working in your webview and not mine. Maybe we are making webview changes right now that might affect this.

@DonJayamanne
Copy link
Contributor Author

U might have to setup the csp (for data and blobs), this here's what we have:

<meta http-equiv="Content-Security-Policy" content="img-src 'self' data: https: http: blob: ${
                    webView.cspSource
                }; default-src 'unsafe-inline' 'unsafe-eval' vscode-resource: data: https: http: blob:;">

@mjbvz mjbvz added the verified Verification succeeded label Jun 5, 2020
@github-actions github-actions bot locked and limited conversation to collaborators Jul 15, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue identified by VS Code Team member as probable bug notebook verified Verification succeeded
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants