Skip to content

Commit 2b0e81f

Browse files
authored
Blazor Stop Requiring unsafe-inline in CSP (#36771)
* Blazor Server Allow Unsafe Inline For: #34428 * Update MonoPlatform.ts * Fix DefaultReconnectDisplay.test * PR Feedback
1 parent 2b8b2dc commit 2b0e81f

File tree

4 files changed

+46
-11
lines changed

4 files changed

+46
-11
lines changed

src/Components/Web.JS/dist/Release/blazor.server.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Components/Web.JS/src/Platform/Circuits/DefaultReconnectDisplay.ts

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,26 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
3737
];
3838

3939
this.modal.style.cssText = modalStyles.join(';');
40-
this.modal.innerHTML = '<h5 style="margin-top: 20px"></h5><button style="margin:5px auto 5px">Retry</button><p>Alternatively, <a href>reload</a></p>';
41-
this.message = this.modal.querySelector('h5')!;
42-
this.button = this.modal.querySelector('button')!;
43-
this.reloadParagraph = this.modal.querySelector('p')!;
40+
41+
this.message = this.document.createElement('h5') as HTMLHeadingElement;
42+
this.message.style.cssText = 'margin-top: 20px';
43+
44+
this.button = this.document.createElement('button') as HTMLButtonElement;
45+
this.button.style.cssText = 'margin:5px auto 5px';
46+
this.button.textContent = 'Retry';
47+
48+
const link = this.document.createElement('a');
49+
link.addEventListener('click', () => location.reload());
50+
link.textContent = 'reload';
51+
52+
this.reloadParagraph = this.document.createElement('p') as HTMLParagraphElement;
53+
this.reloadParagraph.textContent = 'Alternatively, ';
54+
this.reloadParagraph.appendChild(link);
55+
56+
this.modal.appendChild(this.message);
57+
this.modal.appendChild(this.button);
58+
this.modal.appendChild(this.reloadParagraph);
59+
4460
this.loader = this.getLoader();
4561

4662
this.message.after(this.loader);
@@ -63,7 +79,6 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
6379
this.failed();
6480
}
6581
});
66-
this.reloadParagraph.querySelector('a')!.addEventListener('click', () => location.reload());
6782
}
6883

6984
show(): void {
@@ -98,16 +113,34 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
98113
this.button.style.display = 'block';
99114
this.reloadParagraph.style.display = 'none';
100115
this.loader.style.display = 'none';
101-
this.message.innerHTML = 'Reconnection failed. Try <a href>reloading</a> the page if you\'re unable to reconnect.';
102-
this.message.querySelector('a')!.addEventListener('click', () => location.reload());
116+
117+
const errorDescription = this.document.createTextNode('Reconnection failed. Try ');
118+
119+
const link = this.document.createElement('a');
120+
link.textContent = 'reloading';
121+
link.setAttribute('href', '');
122+
link.addEventListener('click', () => location.reload());
123+
124+
const errorInstructions = this.document.createTextNode(' the page if you\'re unable to reconnect.');
125+
126+
this.message.replaceChildren(errorDescription, link, errorInstructions);
103127
}
104128

105129
rejected(): void {
106130
this.button.style.display = 'none';
107131
this.reloadParagraph.style.display = 'none';
108132
this.loader.style.display = 'none';
109-
this.message.innerHTML = 'Could not reconnect to the server. <a href>Reload</a> the page to restore functionality.';
110-
this.message.querySelector('a')!.addEventListener('click', () => location.reload());
133+
134+
const errorDescription = this.document.createTextNode('Could not reconnect to the server. ');
135+
136+
const link = this.document.createElement('a');
137+
link.textContent = 'Reload';
138+
link.setAttribute('href', '');
139+
link.addEventListener('click', () => location.reload());
140+
141+
const errorInstructions = this.document.createTextNode(' the page to restore functionality.');
142+
143+
this.message.replaceChildren(errorDescription, link, errorInstructions);
111144
}
112145

113146
private getLoader(): HTMLDivElement {

src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ function addGlobalModuleScriptTagsToDocument(callback: () => void) {
209209
// The callback is put in the global scope so that it can be run after the script is loaded.
210210
// onload cannot be used in this case for non-file scripts.
211211
window['__wasmmodulecallback__'] = callback;
212+
213+
// Note: Any updates to the following script will require updating the inline script hash if using CSP
212214
scriptElem.text = 'var Module; window.__wasmmodulecallback__(); delete window.__wasmmodulecallback__;';
213215

214216
document.body.appendChild(scriptElem);

src/Components/Web.JS/tests/DefaultReconnectDisplay.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ describe('DefaultReconnectDisplay', () => {
7676
expect(display.loader.style.display).toBe('none');
7777
});
7878

79-
it('update message with current attempt', () => {
79+
it('update message with current attempt', () => {
8080
const maxRetires = 6;
8181
const display = new DefaultReconnectDisplay('test-dialog-id', maxRetires, testDocument, NullLogger.instance);
8282

0 commit comments

Comments
 (0)