@samitouri / QOS-React-2 / commits / 930c9e7eeb

Show warning in UI when duplicate installations of DevTools extension are detected (#22563)

Juan committed Oct 15, 2021 at 11:27 UTC 930c9e7eeb4c9721e1b8dee074c2eef4d1eae5dc
6 files changed +115 -13
packages/react-devtools-extensions/src/background.js
+12 -4
@@ -1,12 +1,19 @@
1 -/* global chrome */
1 +// @flow strict-local
2
3 'use strict';
4
5 -const ports = {};
5 +declare var chrome: any;
6 +
7 +const ports: {
8 + [tab: string]: {|devtools: any, 'content-script': any|},
9 +} = {};
10
11 const IS_FIREFOX = navigator.userAgent.indexOf('Firefox') >= 0;
12
9 -import {EXTENSION_INSTALL_CHECK_MESSAGE} from './constants';
13 +import {
14 + EXTENSION_INSTALL_CHECK,
15 + SHOW_DUPLICATE_EXTENSION_WARNING,
16 +} from './constants';
17
18 chrome.runtime.onConnect.addListener(function(port) {
19 let tab = null;
@@ -120,8 +127,9 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
127
128 chrome.runtime.onMessageExternal.addListener(
129 (request, sender, sendResponse) => {
123 - if (request === EXTENSION_INSTALL_CHECK_MESSAGE) {
130 + if (request === EXTENSION_INSTALL_CHECK) {
131 sendResponse(true);
132 + chrome.runtime.sendMessage(SHOW_DUPLICATE_EXTENSION_WARNING);
133 }
134 },
135 );
packages/react-devtools-extensions/src/checkForDuplicateInstallations.js
+7 -7
@@ -11,13 +11,13 @@ declare var chrome: any;
11
12 import {__DEBUG__} from 'react-devtools-shared/src/constants';
13 import {
14 - EXTENSION_INSTALL_CHECK_MESSAGE,
14 + EXTENSION_INSTALL_CHECK,
15 EXTENSION_INSTALLATION_TYPE,
16 INTERNAL_EXTENSION_ID,
17 LOCAL_EXTENSION_ID,
18 } from './constants';
19
20 -const UNRECOGNIZED_EXTENSION_WARNING =
20 +const UNRECOGNIZED_EXTENSION_ERROR =
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.';
@@ -68,9 +68,9 @@ export function checkForDuplicateInstallations(callback: boolean => void) {
68 // detect if there are other installations of DevTools present.
69 // In this case, assume there are no duplicate exensions and show a warning about
70 // potential conflicts.
71 - console.error(UNRECOGNIZED_EXTENSION_WARNING);
71 + console.error(UNRECOGNIZED_EXTENSION_ERROR);
72 chrome.devtools.inspectedWindow.eval(
73 - `console.error("${UNRECOGNIZED_EXTENSION_WARNING}")`,
73 + `console.error("${UNRECOGNIZED_EXTENSION_ERROR}")`,
74 );
75 callback(false);
76 break;
@@ -80,9 +80,9 @@ export function checkForDuplicateInstallations(callback: boolean => void) {
80 // are other installations of DevTools present.
81 // In this case, assume there are no duplicate exensions and show a warning about
82 // potential conflicts.
83 - console.error(UNRECOGNIZED_EXTENSION_WARNING);
83 + console.error(UNRECOGNIZED_EXTENSION_ERROR);
84 chrome.devtools.inspectedWindow.eval(
85 - `console.error("${UNRECOGNIZED_EXTENSION_WARNING}")`,
85 + `console.error("${UNRECOGNIZED_EXTENSION_ERROR}")`,
86 );
87 callback(false);
88 break;
@@ -105,7 +105,7 @@ function checkForInstalledExtension(extensionId: string): Promise<boolean> {
105 return new Promise(resolve => {
106 chrome.runtime.sendMessage(
107 extensionId,
108 - EXTENSION_INSTALL_CHECK_MESSAGE,
108 + EXTENSION_INSTALL_CHECK,
109 response => {
110 if (__DEBUG__) {
111 console.log(
packages/react-devtools-extensions/src/constants.js
+3 -1
@@ -11,7 +11,9 @@ declare var chrome: any;
11
12 export const CURRENT_EXTENSION_ID = chrome.runtime.id;
13
14 -export const EXTENSION_INSTALL_CHECK_MESSAGE = 'extension-install-check';
14 +export const EXTENSION_INSTALL_CHECK = 'extension-install-check';
15 +export const SHOW_DUPLICATE_EXTENSION_WARNING =
16 + 'show-duplicate-extension-warning';
17
18 export const CHROME_WEBSTORE_EXTENSION_ID = 'fmkadmapgofadopljbjfkapdkoienihi';
19 export const INTERNAL_EXTENSION_ID = 'dnjnjgbfilfphmojnmhliehogmojhclc';
packages/react-devtools-extensions/src/main.js
+34 -1
@@ -22,7 +22,11 @@ import {
22 import DevTools from 'react-devtools-shared/src/devtools/views/DevTools';
23 import {__DEBUG__} from 'react-devtools-shared/src/constants';
24 import {logEvent} from 'react-devtools-shared/src/Logger';
25 -import {CURRENT_EXTENSION_ID, EXTENSION_INSTALLATION_TYPE} from './constants';
25 +import {
26 + CURRENT_EXTENSION_ID,
27 + EXTENSION_INSTALLATION_TYPE,
28 + SHOW_DUPLICATE_EXTENSION_WARNING,
29 +} from './constants';
30 import {checkForDuplicateInstallations} from './checkForDuplicateInstallations';
31
32 const LOCAL_STORAGE_SUPPORTS_PROFILING_KEY =
@@ -108,11 +112,39 @@ function createPanelIfReactLoaded() {
112 let mostRecentOverrideTab = null;
113 let render = null;
114 let root = null;
115 + let warnIfDuplicateInstallation = false;
116
117 const tabId = chrome.devtools.inspectedWindow.tabId;
118
119 registerDevToolsEventLogger('extension');
120
121 + function onDuplicateExtensionMessage(message) {
122 + if (message === SHOW_DUPLICATE_EXTENSION_WARNING) {
123 + chrome.runtime.onMessage.removeListener(
124 + onDuplicateExtensionMessage,
125 + );
126 +
127 + if (warnIfDuplicateInstallation === true) {
128 + return;
129 + }
130 + warnIfDuplicateInstallation = true;
131 + const errorMessage =
132 + 'React Developer Tools: We detected that there are multiple versions of React Developer Tools ' +
133 + 'installed and enabled in your browser at the same time, which will cause ' +
134 + 'issues while using the extension. ' +
135 + 'Please ensure that you have installed and enabled only a single ' +
136 + 'version of React Developer Tools before proceeding.';
137 + console.error(errorMessage);
138 + chrome.devtools.inspectedWindow.eval(
139 + `console.error("${errorMessage}")`,
140 + );
141 + if (render != null) {
142 + render();
143 + }
144 + }
145 + }
146 + chrome.runtime.onMessage.addListener(onDuplicateExtensionMessage);
147 +
148 function initBridgeAndStore() {
149 const port = chrome.runtime.connect({
150 name: String(tabId),
@@ -374,6 +406,7 @@ function createPanelIfReactLoaded() {
406 hookNamesModuleLoaderFunction,
407 overrideTab,
408 profilerPortalContainer,
409 + warnIfDuplicateInstallation,
410 showTabBar: false,
411 store,
412 warnIfUnsupportedVersionDetected: true,
packages/react-devtools-shared/src/devtools/views/DevTools.js
+4
@@ -34,6 +34,7 @@ import {SchedulingProfilerContextController} from 'react-devtools-scheduling-pro
34 import {ModalDialogContextController} from './ModalDialog';
35 import ReactLogo from './ReactLogo';
36 import UnsupportedBridgeProtocolDialog from './UnsupportedBridgeProtocolDialog';
37 +import DuplicateInstallationDialog from './DuplicateInstallationDialog';
38 import UnsupportedVersionDialog from './UnsupportedVersionDialog';
39 import WarnIfLegacyBackendDetected from './WarnIfLegacyBackendDetected';
40 import {useLocalStorage} from './hooks';
@@ -73,6 +74,7 @@ export type Props = {|
74 enabledInspectedElementContextMenu?: boolean,
75 showTabBar?: boolean,
76 store: Store,
77 + warnIfDuplicateInstallation?: boolean,
78 warnIfLegacyBackendDetected?: boolean,
79 warnIfUnsupportedVersionDetected?: boolean,
80 viewAttributeSourceFunction?: ?ViewAttributeSource,
@@ -132,6 +134,7 @@ export default function DevTools({
134 profilerPortalContainer,
135 showTabBar = false,
136 store,
137 + warnIfDuplicateInstallation = false,
138 warnIfLegacyBackendDetected = false,
139 warnIfUnsupportedVersionDetected = false,
140 viewAttributeSourceFunction,
@@ -319,6 +322,7 @@ export default function DevTools({
322 </ViewElementSourceContext.Provider>
323 </SettingsContextController>
324 <UnsupportedBridgeProtocolDialog />
325 + {warnIfDuplicateInstallation && <DuplicateInstallationDialog />}
326 {warnIfLegacyBackendDetected && <WarnIfLegacyBackendDetected />}
327 {warnIfUnsupportedVersionDetected && <UnsupportedVersionDialog />}
328 </ModalDialogContextController>
packages/react-devtools-shared/src/devtools/views/DuplicateInstallationDialog.js new
+55
@@ -0,0 +1,55 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow strict-local
8 + */
9 +
10 +import * as React from 'react';
11 +import {Fragment, useContext, useEffect} from 'react';
12 +import {isInternalFacebookBuild} from 'react-devtools-feature-flags';
13 +import {ModalDialogContext} from './ModalDialog';
14 +
15 +export default function DuplicateInstallationDialog(_: {||}) {
16 + const {dispatch} = useContext(ModalDialogContext);
17 +
18 + useEffect(() => {
19 + dispatch({
20 + canBeDismissed: false,
21 + id: 'DuplicateInstallationDialog',
22 + type: 'SHOW',
23 + title: 'Duplicate Installations of DevTools Detected',
24 + content: <DialogContent />,
25 + });
26 + }, []);
27 + return null;
28 +}
29 +
30 +function DialogContent(_: {||}) {
31 + return (
32 + <Fragment>
33 + <p>
34 + We detected that there are multiple versions of React Developer Tools
35 + installed and enabled in your browser at the same time, which will cause
36 + issues while using the extension.
37 + </p>
38 + {isInternalFacebookBuild ? (
39 + <p>
40 + Before proceeding, please ensure that the only enabled version of
41 + React Developer Tools is the internal (Chef-installed) version. To
42 + manage your extensions, visit the <code>about://extensions</code> page
43 + in your browser.
44 + </p>
45 + ) : (
46 + <p>
47 + Please ensure that you have installed and enabled only a single
48 + version of React Developer Tools before proceeding. To manage your
49 + extensions, visit the <code>about://extensions</code> page in your
50 + browser.
51 + </p>
52 + )}
53 + </Fragment>
54 + );
55 +}