Arnold Rimmer
Arnold Rimmer

Reputation: 3101

Why is JS/CSS not loaded in my VSC extension webview

I'm writing a vsc extenion that uses a webview. The extension itself works fine but the JS and CSS in my webview are not being loaded.

I keep getting errors in the webview console like:

VM102 main.js:12 Refused to load the stylesheet 'vscode-resource://file///full/disc/path/to/vsc-extension/resources/css/webview-package.css' because it violates the following Content Security Policy directive: "style-src nonce-LSAOCrvSSPay9prF40mc5JyRJ9BzFUKR". Note that 'style-src-elem' was not explicitly set, so 'style-src' is used as a fallback.

(anonymous) @ VM102 main.js:12
VM102 main.js:12 Refused to load the script 'vscode-resource://file///full/disc/path/to/vsc-extension/resources/js/webview-package.js' because it violates the following Content Security Policy directive: "script-src nonce-LSAOCrvSSPay9prF40mc5JyRJ9BzFUKR". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

I have the following CSP meta tag in my template for the web view:

<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src nonce-${nonce}; style-src nonce-${nonce};">

This is my webview template:

`<!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src nonce-${nonce}; style-src nonce-${nonce};">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>${packageName}</title>
            <link href="${cssUri}" nonce="${nonce}" rel="stylesheet" type="text/css">
        </head>
        <body>
            <h1 id="${EXT}__name">${packageName}</h1>
            <script nonce="${nonce}" src="${scriptUri}"></script>
        </body>
    </html>`

The paths to the resources are created as shown in the webview docs:

  const scriptPath = vscode.Uri.file(
    path.join(extensionPath, FS_FOLDER_RESOURCES, FS_FOLDER_JS, FS_WEBVIEW_PACKAGE_JS)
  );
  const cssPath = vscode.Uri.file(
    path.join(extensionPath, FS_FOLDER_RESOURCES, FS_FOLDER_CSS, FS_WEBVIEW_PACKAGE_CSS)
  )

I have experimented with various CSP formats and keep having errors, my code is just not loading. It is blocked due to the CSP, but I don't understand why. I followed all the instructions here:

https://code.visualstudio.com/api/extension-guides/webview#content-security-policy

and looked a lots of example CSP tags linked to here:

https://github.com/microsoft/vscode/issues/79340

But still nothing is ever loaded.

Here is my css:

html,
body {
  background: red;
}

h1 {
  background: blue;
}

The JS looks like this:

// This script will be run within the webview itself
// It cannot access the main VS Code APIs directly.
(function () {
  console.log('### test);
  alert('### test');
}());

But I don't think they are the problem as they are blocked due to CSP.

Upvotes: 4

Views: 2762

Answers (2)

David
David

Reputation: 49

For those that arrive here trying to figure out why their css and js load fine in the webview during debugging (F5), but then don't show after packaging (vsce package) I'd like to help.

I was placing my .css and .js files in a folder that held my class implementing webview. Something like /src/components/a/folder/js/some.js and /src/components/a/folder/css/style.css.

But things got mixed up during packaging. After lots of arguing with webpack I moved everything to a media folder off root (like the examples). And the problems cleared up.

My final home was /media/js/some.js and /medida/css/style.css.

Upvotes: 1

Hyeonseo Kim
Hyeonseo Kim

Reputation: 344

I had a similar situation to you. #

The extensionPath is a property of ExtensionContext, You should access the ExtensionContext of your extension first to get extensionPath. In the docs ExtensionContext,

An instance of an ExtensionContext is provided as the first parameter to the activate-call of an extension.

By default, the activate-call of your extension is function activate(context). You can access ExtensionContext using the parameter context in this scope. So if you want to get the path of extension, you should use context.extensionPath.

And I highly recommend adding security policy in the <meta> tag and a local resource contorl in localResourceRoots like below

        vscode.ViewColumn.One,
        {
          // Enable scripts in the webview
          enableScripts: true,
          // Only allow the webview to access resources in our extension's media directory
          localResourceRoots: [vscode.Uri.file(path.join(context.extensionPath, 'media'))]
        }
      );

HTML tag

<meta
  http-equiv="Content-Security-Policy"
  content="default-src 'none'; img-src ${webview.cspSource} https:; script-src ${webview.cspSource}; style-src ${webview.cspSource};"
/>

Security Policy is not activated when you don't write <meta http-equiv="Content-Security-Policy">, it means to allow all resources, but it could occur security issues.

Upvotes: 8

Related Questions