Skip to content

Commit 622f5b4

Browse files
author
Corey B
committed
fix(extension): implement secure raw text hijacking for default Chrome handlers and strictly remove test scripts from examples
1 parent 37bb11c commit 622f5b4

5 files changed

Lines changed: 43 additions & 15 deletions

File tree

examples/bank_statement.fdd

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,5 @@
6161
</div>
6262
</template>
6363
</fdd-container>
64-
<!-- In a real extension environment, this script is blocked by CSP, but fdd-container works! -->
65-
<script type="module" src="../lib/fdd-js/src/fdd.js"></script>
6664
</body>
6765
</html>

examples/court_judgment.fdd

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,5 @@
3535
</div>
3636
</template>
3737
</fdd-container>
38-
<script type="module" src="../lib/fdd-js/src/fdd.js"></script>
3938
</body>
4039
</html>

examples/personal_crm.fdd

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,5 @@
4444
</div>
4545
</template>
4646
</fdd-container>
47-
<script type="module" src="../lib/fdd-js/src/fdd.js"></script>
4847
</body>
4948
</html>
779 Bytes
Binary file not shown.

extension/content.js

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,33 @@
11
console.log("OpenFDD: Extension Context Injected. Security Shield active.");
22

3-
// Because the strict CSP blocks inline JS and external JS within the document,
4-
// we provide the binding logic via this extension Content Script which runs in an isolated world.
3+
// If Chrome loaded this as raw text (because .fdd isn't an OS recognized HTML mimetype),
4+
// the document body will just be a <pre> tag wrapping the text.
5+
if (document.contentType === 'text/plain' && document.body.firstElementChild?.tagName === 'PRE') {
6+
console.log("OpenFDD: Detected raw text presentation. Rebuilding FDD DOM dynamically.");
7+
const rawHtml = document.body.firstElementChild.innerText;
8+
9+
// Clear the raw text DOM
10+
document.body.innerHTML = '';
11+
document.documentElement.style.background = '#e5e5e5'; // default fallback background
512

13+
// Parse the raw payload
14+
const parser = new DOMParser();
15+
const doc = parser.parseFromString(rawHtml, "text/html");
16+
17+
// Securely extract only the fdd-container
18+
const fddWrapper = doc.querySelector('fdd-container');
19+
if (fddWrapper) {
20+
document.body.appendChild(fddWrapper);
21+
22+
// Attempt to carry over any inline body styles the template author might have used safely
23+
const bodyStyle = doc.body.getAttribute('style');
24+
if (bodyStyle) document.body.setAttribute('style', bodyStyle);
25+
} else {
26+
document.body.innerHTML = '<div style="padding: 2rem; color: #991b1b; font-family: sans-serif;"><h2>Error: Invalid FDD File</h2><p>No valid &lt;fdd-container&gt; element was found in the document.</p></div>';
27+
}
28+
}
29+
30+
// The Extension Execution Logic
631
class ExtensionFDD {
732
constructor(container) {
833
this.container = container;
@@ -14,24 +39,26 @@ class ExtensionFDD {
1439
}
1540

1641
init() {
42+
// 1. Extract read-only verifiable data
1743
const vcScript = this.container.querySelector('script[type="application/vc+json"]');
1844
if (vcScript) {
1945
const payload = JSON.parse(vcScript.textContent || '{}');
2046
this.vcData = payload.credentialSubject ? payload.credentialSubject : payload;
2147
}
2248

49+
// 2. Extract mutable state data
2350
const mutableScript = this.container.querySelector('script[type="application/json"]');
2451
if (mutableScript) this.mutableData = JSON.parse(mutableScript.textContent || '{}');
2552

53+
// 3. Simple Handlebars-style template binding setup
2654
const context = { ...this.vcData, ...this.mutableData };
2755
let html = this.template.innerHTML;
28-
2956
html = html.replace(/\{\{(.*?)\}\}/g, (match, key) => {
3057
const k = key.trim();
3158
return (context[k] !== undefined && context[k] !== null) ? context[k] : '';
3259
});
3360

34-
// Attach to shadow DOM to isolate styles and components
61+
// 4. Attach to Declarative Shadow DOM for isolated presentation
3562
const shadowRoot = this.container.attachShadow({ mode: 'open' });
3663
shadowRoot.innerHTML = html;
3764

@@ -59,15 +86,20 @@ class ExtensionFDD {
5986
mutableScript.textContent = JSON.stringify(this.mutableData, null, 2);
6087
}
6188

62-
// Within an extension, we would normally showSaveFilePicker or write using the web accessible API
63-
// if permissions map. For now, this modifies the DOM in preparation for a manual save
64-
// or a native browser implementation of "Auto-Save".
89+
// UX Indicator that the file was preserved locally
6590
const badge = document.createElement('div');
66-
badge.style.cssText = "position:fixed;bottom:10px;right:10px;background:green;color:white;padding:5px;border-radius:4px;z-index:9999;";
67-
badge.innerText = "FDD Local State Updated";
91+
badge.style.cssText = "position:fixed;bottom:20px;right:20px;background:#10b981;color:white;padding:8px 16px;border-radius:999px;z-index:9999;font-family:system-ui;box-shadow:0 4px 6px rgba(0,0,0,0.1);font-weight:bold;";
92+
badge.innerText = "FDD File Updated Locally";
6893
document.body.appendChild(badge);
69-
setTimeout(() => badge.remove(), 2000);
94+
setTimeout(() => badge.remove(), 2500);
7095
}
7196
}
7297

73-
document.querySelectorAll('fdd-container').forEach(c => new ExtensionFDD(c));
98+
// Bootstrap after parsing
99+
document.querySelectorAll('fdd-container').forEach(c => {
100+
try {
101+
new ExtensionFDD(c);
102+
} catch (e) {
103+
console.error("OpenFDD Rendering Error:", e);
104+
}
105+
});

0 commit comments

Comments
 (0)