Skip to content

Commit 29549d9

Browse files
author
Juan Tejada
committed
Local builds now are always enabled over duplicates, build step generates stable id for local builds
1 parent 91920c4 commit 29549d9

File tree

4 files changed

+103
-78
lines changed

4 files changed

+103
-78
lines changed

packages/react-devtools-extensions/build.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,7 @@ const build = async (tempPath, manifestPath) => {
103103
manifest.description += `\n\nCreated from revision ${commit} on ${dateString}.`;
104104

105105
if (process.env.NODE_ENV === 'development') {
106-
if (Array.isArray(manifest.permissions)) {
107-
manifest.permissions.push('management');
108-
}
106+
manifest.key = 'reactdevtoolslocalbuilduniquekey';
109107
}
110108

111109
writeFileSync(copiedManifestPath, JSON.stringify(manifest, null, 2));

packages/react-devtools-extensions/src/checkForDuplicateInstallations.js

Lines changed: 83 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -14,98 +14,75 @@ import {
1414
EXTENSION_INSTALL_CHECK_MESSAGE,
1515
EXTENSION_INSTALLATION_TYPE,
1616
INTERNAL_EXTENSION_ID,
17-
EXTENSION_NAME,
17+
LOCAL_EXTENSION_ID,
1818
} from './constants';
1919

20+
const UNRECOGNIZED_EXTENSION_WARNING =
21+
'React Developer Tools: You are running an unrecognized installation of the React Developer Tools extension, which might conflict with other versions of the extension installed in your browser. ' +
22+
'Please make sure you only have a single version of the extension installed or enabled. ' +
23+
'If you are developing this extension locally, make sure to build the extension using the `yarn build:<browser>:local` command.';
24+
2025
export function checkForDuplicateInstallations(callback: boolean => void) {
2126
switch (EXTENSION_INSTALLATION_TYPE) {
2227
case 'public': {
2328
// If this is the public extension (e.g. from Chrome Web Store), check if an internal
24-
// build of the extension is also installed, and if so, disable this extension.
25-
chrome.runtime.sendMessage(
29+
// or local build of the extension is also installed, and if so, disable this extension.
30+
checkForInstalledExtensions([
2631
INTERNAL_EXTENSION_ID,
27-
EXTENSION_INSTALL_CHECK_MESSAGE,
28-
response => {
29-
if (__DEBUG__) {
30-
console.log(
31-
'checkForDuplicateInstallations: Duplicate installation check responded with',
32-
{
33-
response,
34-
error: chrome.runtime.lastError?.message,
35-
currentExtension: EXTENSION_INSTALLATION_TYPE,
36-
},
37-
);
38-
}
39-
if (chrome.runtime.lastError != null) {
40-
callback(false);
41-
} else {
42-
callback(true);
43-
}
44-
},
45-
);
32+
LOCAL_EXTENSION_ID,
33+
]).then(areExtensionsInstalled => {
34+
if (areExtensionsInstalled.some(isInstalled => isInstalled)) {
35+
callback(true);
36+
} else {
37+
callback(false);
38+
}
39+
});
4640
break;
4741
}
4842
case 'internal': {
49-
// If this is the internal extension, keep this one enabled.
50-
// Other installations disable themselves if they detect this installation.
43+
// If this is the internal extension, check if a local build of the extension
44+
// is also installed, and if so, disable this extension.
45+
// If the public version of the extension is also installed, that extension
46+
// will disable itself.
5147
// TODO show warning if other installations are present.
52-
callback(false);
48+
checkForInstalledExtension(LOCAL_EXTENSION_ID).then(isInstalled => {
49+
if (isInstalled) {
50+
callback(true);
51+
} else {
52+
callback(false);
53+
}
54+
});
5355
break;
5456
}
55-
case 'unknown': {
57+
case 'local': {
5658
if (__DEV__) {
57-
// If this extension was built locally during development, then we check for other
58-
// installations of the extension via the `chrome.management` API (which is only
59-
// enabled in local development builds).
60-
// If we detect other installations, we disable this one and show a warning
61-
// for the developer to disable the other installations.
62-
// NOTE: Ideally in this case we would disable any other extensions except the
63-
// development one. However, since we don't have a stable extension ID for dev builds,
64-
// doing so would require for other installations to wait for a message from this extension,
65-
// which would unnecessarily delay initialization of those extensions.
66-
chrome.management.getAll(extensions => {
67-
if (chrome.runtime.lastError != null) {
68-
const errorMessage =
69-
'React Developer Tools: Unable to access `chrome.management` to check for duplicate extensions. This extension will be disabled. ' +
70-
'If you are developing this extension locally, make sure to build the extension using the `yarn build:<browser>:local` command.';
71-
console.error(errorMessage);
72-
chrome.devtools.inspectedWindow.eval(
73-
`console.error("${errorMessage}")`,
74-
);
75-
callback(true);
76-
return;
77-
}
78-
const devToolsExtensions = extensions.filter(
79-
extension => extension.name === EXTENSION_NAME && extension.enabled,
80-
);
81-
if (devToolsExtensions.length > 1) {
82-
// TODO: Show warning in UI of extension that remains enabled
83-
const errorMessage =
84-
'React Developer Tools: You are running multiple installations of the React Developer Tools extension, which will conflict with this development build of the extension. ' +
85-
'In order to prevent conflicts, this development build of the extension will be disabled. In order to continue local development, please disable or uninstall ' +
86-
'any other installations of the extension in your browser.';
87-
chrome.devtools.inspectedWindow.eval(
88-
`console.error("${errorMessage}")`,
89-
);
90-
console.error(errorMessage);
91-
callback(true);
92-
} else {
93-
callback(false);
94-
}
95-
});
59+
// If this is the local extension (i.e. built locally during development),
60+
// always keep this one enabled. Other installations disable themselves if
61+
// they detect the local build is installed.
62+
callback(false);
9663
break;
9764
}
9865

9966
// If this extension wasn't built locally during development, we can't reliably
10067
// detect if there are other installations of DevTools present.
10168
// In this case, assume there are no duplicate exensions and show a warning about
10269
// potential conflicts.
103-
const warnMessage =
104-
'React Developer Tools: You are running an unrecognized installation of the React Developer Tools extension, which might conflict with other versions of the extension installed in your browser. ' +
105-
'Please make sure you only have a single version of the extension installed or enabled. ' +
106-
'If you are developing this extension locally, make sure to build the extension using the `yarn build:<browser>:local` command.';
107-
console.warn(warnMessage);
108-
chrome.devtools.inspectedWindow.eval(`console.warn("${warnMessage}")`);
70+
console.error(UNRECOGNIZED_EXTENSION_WARNING);
71+
chrome.devtools.inspectedWindow.eval(
72+
`console.error("${UNRECOGNIZED_EXTENSION_WARNING}")`,
73+
);
74+
callback(false);
75+
break;
76+
}
77+
case 'unknown': {
78+
// If we don't know how this extension was built, we can't reliably detect if there
79+
// are other installations of DevTools present.
80+
// In this case, assume there are no duplicate exensions and show a warning about
81+
// potential conflicts.
82+
console.error(UNRECOGNIZED_EXTENSION_WARNING);
83+
chrome.devtools.inspectedWindow.eval(
84+
`console.error("${UNRECOGNIZED_EXTENSION_WARNING}")`,
85+
);
10986
callback(false);
11087
break;
11188
}
@@ -114,3 +91,38 @@ export function checkForDuplicateInstallations(callback: boolean => void) {
11491
}
11592
}
11693
}
94+
95+
function checkForInstalledExtensions(
96+
extensionIds: string[],
97+
): Promise<boolean[]> {
98+
return Promise.all(
99+
extensionIds.map(extensionId => checkForInstalledExtension(extensionId)),
100+
);
101+
}
102+
103+
function checkForInstalledExtension(extensionId: string): Promise<boolean> {
104+
return new Promise(resolve => {
105+
chrome.runtime.sendMessage(
106+
extensionId,
107+
EXTENSION_INSTALL_CHECK_MESSAGE,
108+
response => {
109+
if (__DEBUG__) {
110+
console.log(
111+
'checkForDuplicateInstallations: Duplicate installation check responded with',
112+
{
113+
response,
114+
error: chrome.runtime.lastError?.message,
115+
currentExtension: EXTENSION_INSTALLATION_TYPE,
116+
checkingExtension: extensionId,
117+
},
118+
);
119+
}
120+
if (chrome.runtime.lastError != null) {
121+
resolve(false);
122+
} else {
123+
resolve(true);
124+
}
125+
},
126+
);
127+
});
128+
}

packages/react-devtools-extensions/src/constants.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,23 @@ declare var chrome: any;
1111

1212
export const CURRENT_EXTENSION_ID = chrome.runtime.id;
1313

14-
export const EXTENSION_NAME = 'React Developer Tools';
1514
export const EXTENSION_INSTALL_CHECK_MESSAGE = 'extension-install-check';
1615

17-
export const CHROME_WEBSTORE_EXTENSION_ID = 'fmkadmapgofadopljbjfkapdkoienihi';
18-
export const INTERNAL_EXTENSION_ID = 'dnjnjgbfilfphmojnmhliehogmojhclc';
16+
// export const CHROME_WEBSTORE_EXTENSION_ID = 'fmkadmapgofadopljbjfkapdkoienihi';
17+
// export const INTERNAL_EXTENSION_ID = 'dnjnjgbfilfphmojnmhliehogmojhclc';
18+
export const CHROME_WEBSTORE_EXTENSION_ID = 'blaipngpacjhjmfmchjgmhmlhjemncgl';
19+
export const INTERNAL_EXTENSION_ID = 'bpocpipemfjjfjefjdnikdhpgmbanpla';
20+
export const LOCAL_EXTENSION_ID = 'ikiahnapldjmdmpkmfhjdjilojjhgcbf';
1921

20-
export const EXTENSION_INSTALLATION_TYPE: 'public' | 'internal' | 'unknown' =
22+
export const EXTENSION_INSTALLATION_TYPE:
23+
| 'public'
24+
| 'internal'
25+
| 'local'
26+
| 'unknown' =
2127
CURRENT_EXTENSION_ID === CHROME_WEBSTORE_EXTENSION_ID
2228
? 'public'
2329
: CURRENT_EXTENSION_ID === INTERNAL_EXTENSION_ID
2430
? 'internal'
31+
: CURRENT_EXTENSION_ID === LOCAL_EXTENSION_ID
32+
? 'local'
2533
: 'unknown';

packages/react-devtools-extensions/src/main.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ function createPanelIfReactLoaded() {
8585
return;
8686
}
8787

88+
if (__DEBUG__) {
89+
console.log(
90+
'[main] createPanelIfReactLoaded: No duplicate installations detected, continuing with initialization.',
91+
{currentExtension: EXTENSION_INSTALLATION_TYPE},
92+
);
93+
}
94+
8895
panelCreated = true;
8996

9097
clearInterval(loadCheckInterval);

0 commit comments

Comments
 (0)