Skip to content
Open
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
12 changes: 12 additions & 0 deletions devtools/projects/shell-browser/src/app/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,19 @@ function getPopUpName(ng: AngularDetection): string {
return 'supported.html';
}

function checkGoogler(): void {
fetch('https://g3doc.corp.google.com/does/not/exist/for/angular/devtools', {
mode: 'no-cors',
})
.then(() => chrome.storage.local.set({isGoogler: true}))
.catch(() => chrome.storage.local.set({isGoogler: false}));
}

if (chrome !== undefined && chrome.runtime !== undefined) {
// Check on extension install/update as well as on every background service worker startup/wake-up.
chrome.runtime.onInstalled?.addListener(checkGoogler);
checkGoogler();
Comment thread
eduhmc marked this conversation as resolved.

const isManifestV3 = chrome.runtime.getManifest().manifest_version === 3;

const browserAction = (() => {
Expand Down
124 changes: 66 additions & 58 deletions devtools/projects/shell-browser/src/devtools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,69 +16,77 @@
const DEEP_LINK_SCHEME = 'angular-devtools';

const theme = chrome.devtools.panels.themeName;
chrome.devtools.panels.create(
'Angular',
// Firefox specifically displays the icon in the tab.
// the bw icon wasn't visible in dark mode
theme === 'dark' ? 'assets/icon16.png' : 'assets/icon-bw16.png',
'index.html',
(panel) => {
// Keep a reference to the panel's window so we can post messages
// even if the panel is already visible (onShown won't re-fire).
let currentPanelWindow: Window | null = null;
panel.onShown.addListener((panelWindow: Window) => {
currentPanelWindow = panelWindow;
});
panel.onHidden.addListener(() => {
currentPanelWindow = null;
});

// Register a handler for deep links from the Chrome Performance panel.
// When the user clicks on an Angular performance entry (e.g. a component lifecycle hook),
// Chrome calls this handler with the deep link URL, activating the Angular DevTools panel
// and navigating to the relevant component.
//
// The optional `urlScheme` second parameter on `setOpenResourceHandler` is a Chrome 140+
// extension that registers this handler exclusively for URLs with the given scheme.
// It is not yet reflected in the official chrome.devtools.panels in @types/chrome
// see: https://issues.chromium.org/issues/427430112
//
// NOTE: This feature requires the following Chrome flag to be enabled:
// chrome://flags/#enable-devtools-deep-link-via-extensibility-api
type OpenResourceHandler = (
callback: (resource: {url: string}) => void,
urlScheme?: string,
) => void;
chrome.storage.local.get('isGoogler', (res) => {
const isGoogler = res['isGoogler'] !== false;

@csmick csmick Jul 22, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this set isGoogler to true if it isn't present in local storage? Is it ever possible it's absent? If so, should false be the default instead?

createDevToolsPanel(isGoogler ? 'Angular & Wiz' : 'Angular');
});

const setHandler = chrome.devtools.panels.setOpenResourceHandler as OpenResourceHandler;
function createDevToolsPanel(title: string) {
chrome.devtools.panels.create(
title,
// Firefox specifically displays the icon in the tab.
// the bw icon wasn't visible in dark mode
theme === 'dark' ? 'assets/icon16.png' : 'assets/icon-bw16.png',
'index.html',
(panel) => {
// Keep a reference to the panel's window so we can post messages
// even if the panel is already visible (onShown won't re-fire).
let currentPanelWindow: Window | null = null;
panel.onShown.addListener((panelWindow: Window) => {
currentPanelWindow = panelWindow;
});
panel.onHidden.addListener(() => {
currentPanelWindow = null;
});

setHandler((resource: {url: string}) => {
// Extract the instance ID from "angular-devtools://component/{instanceId}".
const match = resource.url.match(/^angular-devtools:\/\/component\/(\d+)$/);
if (!match) return;
// Register a handler for deep links from the Chrome Performance panel.
// When the user clicks on an Angular performance entry (e.g. a component lifecycle hook),
// Chrome calls this handler with the deep link URL, activating the Angular DevTools panel
// and navigating to the relevant component.
//
// The optional `urlScheme` second parameter on `setOpenResourceHandler` is a Chrome 140+
// extension that registers this handler exclusively for URLs with the given scheme.
// It is not yet reflected in the official chrome.devtools.panels in @types/chrome
// see: https://issues.chromium.org/issues/427430112
//
// NOTE: This feature requires the following Chrome flag to be enabled:
// chrome://flags/#enable-devtools-deep-link-via-extensibility-api
type OpenResourceHandler = (
callback: (resource: {url: string}) => void,
urlScheme?: string,
) => void;

const instanceId = parseInt(match[1], 10);
const setHandler = chrome.devtools.panels.setOpenResourceHandler as OpenResourceHandler;

panel.show();
setHandler((resource: {url: string}) => {
// Extract the instance ID from "angular-devtools://component/{instanceId}".
const match = resource.url.match(/^angular-devtools:\/\/component\/(\d+)$/);
if (!match) return;

// Post immediately if the panel is already visible; otherwise wait for onShown.
if (currentPanelWindow) {
currentPanelWindow.postMessage({type: 'angular-devtools-deep-link', instanceId}, '*');
} else {
const onShown = (panelWindow: Window) => {
panel.onShown.removeListener(onShown);
const instanceId = parseInt(match[1], 10);

panelWindow.postMessage(
{
type: 'angular-devtools-deep-link',
instanceId,
},
'*',
);
};
panel.show();

panel.onShown.addListener(onShown);
}
}, DEEP_LINK_SCHEME);
},
);
// Post immediately if the panel is already visible; otherwise wait for onShown.
if (currentPanelWindow) {
currentPanelWindow.postMessage({type: 'angular-devtools-deep-link', instanceId}, '*');
} else {
const onShown = (panelWindow: Window) => {
panel.onShown.removeListener(onShown);

panelWindow.postMessage(
{
type: 'angular-devtools-deep-link',
instanceId,
},
'*',
);
};

panel.onShown.addListener(onShown);
}
}, DEEP_LINK_SCHEME);
},
);
}
Loading