Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Oct 15, 2021
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
16 changes: 12 additions & 4 deletions packages/react-devtools-extensions/src/background.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
/* global chrome */
// @flow strict-local

'use strict';

const ports = {};
declare var chrome: any;

const ports: {
[tab: string]: {|devtools: any, 'content-script': any|},
} = {};

const IS_FIREFOX = navigator.userAgent.indexOf('Firefox') >= 0;

import {EXTENSION_INSTALL_CHECK_MESSAGE} from './constants';
import {
EXTENSION_INSTALL_CHECK,
SHOW_DUPLICATE_EXTENSION_WARNING,
} from './constants';

chrome.runtime.onConnect.addListener(function(port) {
let tab = null;
Expand Down Expand Up @@ -120,8 +127,9 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {

chrome.runtime.onMessageExternal.addListener(
(request, sender, sendResponse) => {
if (request === EXTENSION_INSTALL_CHECK_MESSAGE) {
if (request === EXTENSION_INSTALL_CHECK) {
sendResponse(true);
chrome.runtime.sendMessage(SHOW_DUPLICATE_EXTENSION_WARNING);
}
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ declare var chrome: any;

import {__DEBUG__} from 'react-devtools-shared/src/constants';
import {
EXTENSION_INSTALL_CHECK_MESSAGE,
EXTENSION_INSTALL_CHECK,
EXTENSION_INSTALLATION_TYPE,
INTERNAL_EXTENSION_ID,
LOCAL_EXTENSION_ID,
} from './constants';

const UNRECOGNIZED_EXTENSION_WARNING =
const UNRECOGNIZED_EXTENSION_ERROR =
'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. ' +
'Please make sure you only have a single version of the extension installed or enabled. ' +
'If you are developing this extension locally, make sure to build the extension using the `yarn build:<browser>:local` command.';
Expand Down Expand Up @@ -68,9 +68,9 @@ export function checkForDuplicateInstallations(callback: boolean => void) {
// detect if there are other installations of DevTools present.
// In this case, assume there are no duplicate exensions and show a warning about
// potential conflicts.
console.error(UNRECOGNIZED_EXTENSION_WARNING);
console.error(UNRECOGNIZED_EXTENSION_ERROR);
chrome.devtools.inspectedWindow.eval(
`console.error("${UNRECOGNIZED_EXTENSION_WARNING}")`,
`console.error("${UNRECOGNIZED_EXTENSION_ERROR}")`,
);
callback(false);
break;
Expand All @@ -80,9 +80,9 @@ export function checkForDuplicateInstallations(callback: boolean => void) {
// are other installations of DevTools present.
// In this case, assume there are no duplicate exensions and show a warning about
// potential conflicts.
console.error(UNRECOGNIZED_EXTENSION_WARNING);
console.error(UNRECOGNIZED_EXTENSION_ERROR);
chrome.devtools.inspectedWindow.eval(
`console.error("${UNRECOGNIZED_EXTENSION_WARNING}")`,
`console.error("${UNRECOGNIZED_EXTENSION_ERROR}")`,
);
callback(false);
break;
Expand All @@ -105,7 +105,7 @@ function checkForInstalledExtension(extensionId: string): Promise<boolean> {
return new Promise(resolve => {
chrome.runtime.sendMessage(
extensionId,
EXTENSION_INSTALL_CHECK_MESSAGE,
EXTENSION_INSTALL_CHECK,
response => {
if (__DEBUG__) {
console.log(
Expand Down
4 changes: 3 additions & 1 deletion packages/react-devtools-extensions/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ declare var chrome: any;

export const CURRENT_EXTENSION_ID = chrome.runtime.id;

export const EXTENSION_INSTALL_CHECK_MESSAGE = 'extension-install-check';
export const EXTENSION_INSTALL_CHECK = 'extension-install-check';
export const SHOW_DUPLICATE_EXTENSION_WARNING =
'show-duplicate-extension-warning';

export const CHROME_WEBSTORE_EXTENSION_ID = 'fmkadmapgofadopljbjfkapdkoienihi';
export const INTERNAL_EXTENSION_ID = 'dnjnjgbfilfphmojnmhliehogmojhclc';
Expand Down
35 changes: 34 additions & 1 deletion packages/react-devtools-extensions/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ import {
import DevTools from 'react-devtools-shared/src/devtools/views/DevTools';
import {__DEBUG__} from 'react-devtools-shared/src/constants';
import {logEvent} from 'react-devtools-shared/src/Logger';
import {CURRENT_EXTENSION_ID, EXTENSION_INSTALLATION_TYPE} from './constants';
import {
CURRENT_EXTENSION_ID,
EXTENSION_INSTALLATION_TYPE,
SHOW_DUPLICATE_EXTENSION_WARNING,
} from './constants';
import {checkForDuplicateInstallations} from './checkForDuplicateInstallations';

const LOCAL_STORAGE_SUPPORTS_PROFILING_KEY =
Expand Down Expand Up @@ -108,11 +112,39 @@ function createPanelIfReactLoaded() {
let mostRecentOverrideTab = null;
let render = null;
let root = null;
let warnIfDuplicateInstallation = false;

const tabId = chrome.devtools.inspectedWindow.tabId;

registerDevToolsEventLogger('extension');

function onDuplicateExtensionMessage(message) {
if (message === SHOW_DUPLICATE_EXTENSION_WARNING) {
chrome.runtime.onMessage.removeListener(
onDuplicateExtensionMessage,
);

if (warnIfDuplicateInstallation === true) {
jstejada marked this conversation as resolved.
Show resolved Hide resolved
return;
}
warnIfDuplicateInstallation = true;
const errorMessage =
'React Developer Tools: We detected that there are multiple versions of React Developer Tools ' +
'installed and enabled in your browser at the same time, which will cause ' +
'issues while using the extension. ' +
'Please ensure that you have installed and enabled only a single ' +
'version of React Developer Tools before proceeding.';
console.error(errorMessage);
chrome.devtools.inspectedWindow.eval(
`console.error("${errorMessage}")`,
);
if (render != null) {
render();
}
}
}
chrome.runtime.onMessage.addListener(onDuplicateExtensionMessage);

function initBridgeAndStore() {
const port = chrome.runtime.connect({
name: String(tabId),
Expand Down Expand Up @@ -374,6 +406,7 @@ function createPanelIfReactLoaded() {
hookNamesModuleLoaderFunction,
overrideTab,
profilerPortalContainer,
warnIfDuplicateInstallation,
showTabBar: false,
store,
warnIfUnsupportedVersionDetected: true,
Expand Down
4 changes: 4 additions & 0 deletions packages/react-devtools-shared/src/devtools/views/DevTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {SchedulingProfilerContextController} from 'react-devtools-scheduling-pro
import {ModalDialogContextController} from './ModalDialog';
import ReactLogo from './ReactLogo';
import UnsupportedBridgeProtocolDialog from './UnsupportedBridgeProtocolDialog';
import DuplicateInstallationDialog from './DuplicateInstallationDialog';
import UnsupportedVersionDialog from './UnsupportedVersionDialog';
import WarnIfLegacyBackendDetected from './WarnIfLegacyBackendDetected';
import {useLocalStorage} from './hooks';
Expand Down Expand Up @@ -73,6 +74,7 @@ export type Props = {|
enabledInspectedElementContextMenu?: boolean,
showTabBar?: boolean,
store: Store,
warnIfDuplicateInstallation?: boolean,
warnIfLegacyBackendDetected?: boolean,
warnIfUnsupportedVersionDetected?: boolean,
viewAttributeSourceFunction?: ?ViewAttributeSource,
Expand Down Expand Up @@ -132,6 +134,7 @@ export default function DevTools({
profilerPortalContainer,
showTabBar = false,
store,
warnIfDuplicateInstallation = false,
warnIfLegacyBackendDetected = false,
warnIfUnsupportedVersionDetected = false,
viewAttributeSourceFunction,
Expand Down Expand Up @@ -319,6 +322,7 @@ export default function DevTools({
</ViewElementSourceContext.Provider>
</SettingsContextController>
<UnsupportedBridgeProtocolDialog />
{warnIfDuplicateInstallation && <DuplicateInstallationDialog />}
{warnIfLegacyBackendDetected && <WarnIfLegacyBackendDetected />}
{warnIfUnsupportedVersionDetected && <UnsupportedVersionDialog />}
</ModalDialogContextController>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
*/

import * as React from 'react';
import {Fragment, useContext, useEffect} from 'react';
import {isInternalFacebookBuild} from 'react-devtools-feature-flags';
import {ModalDialogContext} from './ModalDialog';

export default function DuplicateInstallationDialog(_: {||}) {
const {dispatch} = useContext(ModalDialogContext);

useEffect(() => {
dispatch({
canBeDismissed: false,
id: 'DuplicateInstallationDialog',
type: 'SHOW',
title: 'Duplicate Installations of DevTools Detected',
content: <DialogContent />,
});
}, []);
return null;
}

function DialogContent(_: {||}) {
return (
<Fragment>
<p>
We detected that there are multiple versions of React Developer Tools
installed and enabled in your browser at the same time, which will cause
issues while using the extension.
</p>
{isInternalFacebookBuild ? (
<p>
Before proceeding, please ensure that the only enabled version of
React Developer Tools is the internal (Chef-installed) version. To
manage your extensions, visit the <code>about://extensions</code> page
in your browser.
</p>
) : (
<p>
Please ensure that you have installed and enabled only a single
version of React Developer Tools before proceeding. To manage your
extensions, visit the <code>about://extensions</code> page in your
browser.
</p>
)}
</Fragment>
);
}