Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,12 @@ extension/
"description": "Inspect Angular components, signals, DI, and routes.",
"devtools_page": "devtools.html",
"permissions": ["scripting"],
"host_permissions": ["<all_urls>"],
"host_permissions": [
"http://localhost/*",
"https://localhost/*",
"http://127.0.0.1/*",
"https://127.0.0.1/*"
],
"icons": {
"128": "icon-128.png"
}
Expand Down
6 changes: 3 additions & 3 deletions docs/privacy-policy.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ <h2>Data Collection</h2>
</ul>

<h2>What the Extension Accesses</h2>
<p>The Extension accesses the following information <strong>only on the page you are actively inspecting</strong> via Chrome DevTools:</p>
<p>The Extension accesses the following information from pages where its content scripts run and from the page you are actively inspecting via Chrome DevTools:</p>
<ul>
<li><strong>Angular framework detection</strong> — checks for the <code>ng-version</code> HTML attribute and the <code>window.ng</code> global to determine if the page uses Angular</li>
<li><strong>Angular framework detection</strong> — on every page, checks for the <code>ng-version</code> HTML attribute and the <code>window.ng</code> global to determine if the page uses Angular</li>
<li><strong>Angular debug APIs</strong> — reads component trees, signal graphs, dependency injection hierarchies, and route configurations using Angular's built-in debug utilities (available only in development builds)</li>
<li><strong>Localhost communication</strong> — communicates with a devframe server running on <code>localhost</code> on the developer's own machine for live inspection data</li>
</ul>
<p>All data processing happens entirely within your browser and your local machine. No information ever leaves your device.</p>

<h2>Host Permissions</h2>
<p>The Extension requests host permissions (<code>&lt;all_urls&gt;</code>) solely to inject a lightweight content script that detects Angular on any page. The content script only checks for the presence of Angular and does not read or modify page content.</p>
<p>The Extension requests host permissions only for <code>localhost</code> and <code>127.0.0.1</code>, to reach the devframe server on the developer's own machine. The <code>detect-angular.js</code> content script runs on every page, including when DevTools is closed. It reads only the <code>ng-version</code> attribute and whether <code>window.ng</code> exists, to detect Angular. It does not modify page content.</p>

<h2>Data Storage</h2>
<p>The Extension does not persist any data between sessions. All inspection data exists only in memory while the DevTools panel is open and is discarded when the panel is closed.</p>
Expand Down
8 changes: 0 additions & 8 deletions extension/content-script.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
// Inject a page-level script to detect Angular, since content scripts
// can't access the page's JS globals directly.

const script = document.createElement('script');
script.src = chrome.runtime.getURL('detect-angular.js');
script.onload = () => script.remove();
(document.head || document.documentElement).appendChild(script);

// Listen for the detection result posted from the page context
window.addEventListener('message', (event) => {
if (event.source !== window) return;
Expand Down
24 changes: 15 additions & 9 deletions extension/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,26 @@
"name": "Angular DevTools",
"version": "0.0.1",
"description": "Inspect Angular components, signals, dependency injection, and routes.",
"minimum_chrome_version": "111",
"devtools_page": "devtools.html",
"permissions": [],
"host_permissions": ["<all_urls>"],
"host_permissions": [
"http://localhost/*",
"https://localhost/*",
"http://127.0.0.1/*",
"https://127.0.0.1/*"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content-script.js"],
"run_at": "document_idle"
"run_at": "document_start"
},
{
"matches": ["<all_urls>"],
"js": ["detect-angular.js"],
"run_at": "document_idle",
"world": "MAIN"
}
],
"background": {
Expand All @@ -20,11 +32,5 @@
"16": "icons/icon-16.png",
"48": "icons/icon-48.png",
"128": "icons/icon-128.png"
},
"web_accessible_resources": [
{
"resources": ["detect-angular.js"],
"matches": ["<all_urls>"]
}
]
}
}
11 changes: 8 additions & 3 deletions extension/panel-bridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const frame = document.getElementById('devtools-frame');
const status = document.getElementById('status');

const tabId = chrome.devtools.inspectedWindow.tabId;
const LOCAL_HOSTS = ['localhost', '127.0.0.1'];

// Try to find the devframe connection on the inspected page
function detectConnection() {
Expand Down Expand Up @@ -35,7 +36,7 @@ function detectConnection() {
return null;
})()`,
(result, err) => {
if (result && result.base) {
if (result && paths.includes(result.base)) {
loadPanel(result.base);
} else {
// No live devframe found — load in standalone/static mode
Expand All @@ -55,8 +56,12 @@ function loadPanel(baseURL) {
if (baseURL) {
// Get the inspected page's origin to build the full baseURL
chrome.devtools.inspectedWindow.eval('location.origin', (origin) => {
const fullBase = origin + baseURL;
frame.src = `${panelUrl}?baseURL=${encodeURIComponent(fullBase)}`;
const url = new URL(baseURL, origin);
if (!LOCAL_HOSTS.includes(url.hostname)) {
frame.src = panelUrl;
return;
}
frame.src = `${panelUrl}?baseURL=${encodeURIComponent(url.href)}`;
});
} else {
frame.src = panelUrl;
Expand Down
Loading