Skip to content

Commit 22ef96a

Browse files
author
Brian Vaughn
authored
Devtools renable copy attr context menu for firefox (#17740)
* Use exportFunction() to share clipboard copy with JS running in document/page context. * Remove no-longer-used option to disable copy operation.
1 parent 2b903da commit 22ef96a

File tree

8 files changed

+37
-23
lines changed

8 files changed

+37
-23
lines changed

packages/react-devtools-extensions/firefox/manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
"scripts": ["build/background.js"]
4545
},
4646

47-
"permissions": ["file:///*", "http://*/*", "https://*/*"],
47+
"permissions": ["file:///*", "http://*/*", "https://*/*", "clipboardWrite"],
4848

4949
"content_scripts": [
5050
{

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

+16
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,19 @@ if (document.contentType === 'text/html') {
9797
detectReact,
9898
);
9999
}
100+
101+
if (typeof exportFunction === 'function') {
102+
// eslint-disable-next-line no-undef
103+
exportFunction(
104+
text => {
105+
// Call clipboard.writeText from the extension content script
106+
// (as it has the clipboardWrite permission) and return a Promise
107+
// accessible to the webpage js code.
108+
return new window.Promise((resolve, reject) =>
109+
window.navigator.clipboard.writeText(text).then(resolve, reject),
110+
);
111+
},
112+
window.wrappedJSObject.__REACT_DEVTOOLS_GLOBAL_HOOK__,
113+
{defineAs: 'clipboardCopyText'},
114+
);
115+
}

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

-1
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ function createPanelIfReactLoaded() {
211211
browserTheme: getBrowserTheme(),
212212
componentsPortalContainer,
213213
enabledInspectedElementContextMenu: true,
214-
enabledInspectedElementContextMenuCopy: isChrome,
215214
overrideTab,
216215
profilerPortalContainer,
217216
showTabBar: false,

packages/react-devtools-shared/src/backend/utils.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,19 @@ export function cleanForBridge(
4040

4141
export function copyToClipboard(value: any): void {
4242
const safeToCopy = serializeToString(value);
43-
copy(safeToCopy === undefined ? 'undefined' : safeToCopy);
43+
const text = safeToCopy === undefined ? 'undefined' : safeToCopy;
44+
const {clipboardCopyText} = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
45+
46+
// On Firefox navigator.clipboard.writeText has to be called from
47+
// the content script js code (because it requires the clipboardWrite
48+
// permission to be allowed out of a "user handling" callback),
49+
// clipboardCopyText is an helper injected into the page from.
50+
// injectGlobalHook.
51+
if (typeof clipboardCopyText === 'function') {
52+
clipboardCopyText(text).catch(err => {});
53+
} else {
54+
copy(text);
55+
}
4456
}
4557

4658
export function copyWithSet(

packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.js

+6-9
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,6 @@ function InspectedElementView({
303303

304304
const {
305305
isEnabledForInspectedElement,
306-
supportsCopyOperation,
307306
viewAttributeSourceFunction,
308307
} = useContext(ContextMenuContext);
309308

@@ -445,14 +444,12 @@ function InspectedElementView({
445444
<ContextMenu id="SelectedElement">
446445
{data => (
447446
<Fragment>
448-
{supportsCopyOperation && (
449-
<ContextMenuItem
450-
onClick={() => copyInspectedElementPath(id, data.path)}
451-
title="Copy value to clipboard">
452-
<Icon className={styles.ContextMenuIcon} type="copy" /> Copy
453-
value to clipboard
454-
</ContextMenuItem>
455-
)}
447+
<ContextMenuItem
448+
onClick={() => copyInspectedElementPath(id, data.path)}
449+
title="Copy value to clipboard">
450+
<Icon className={styles.ContextMenuIcon} type="copy" /> Copy
451+
value to clipboard
452+
</ContextMenuItem>
456453
<ContextMenuItem
457454
onClick={() => storeAsGlobal(id, data.path)}
458455
title="Store as global variable">

packages/react-devtools-shared/src/devtools/views/DevTools.js

+1-8
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ export type Props = {|
5454
canViewElementSourceFunction?: ?CanViewElementSource,
5555
defaultTab?: TabID,
5656
enabledInspectedElementContextMenu?: boolean,
57-
enabledInspectedElementContextMenuCopy?: boolean,
5857
showTabBar?: boolean,
5958
store: Store,
6059
warnIfLegacyBackendDetected?: boolean,
@@ -97,7 +96,6 @@ export default function DevTools({
9796
componentsPortalContainer,
9897
defaultTab = 'components',
9998
enabledInspectedElementContextMenu = false,
100-
enabledInspectedElementContextMenuCopy = false,
10199
overrideTab,
102100
profilerPortalContainer,
103101
showTabBar = false,
@@ -123,14 +121,9 @@ export default function DevTools({
123121
const contextMenu = useMemo(
124122
() => ({
125123
isEnabledForInspectedElement: enabledInspectedElementContextMenu,
126-
supportsCopyOperation: enabledInspectedElementContextMenuCopy,
127124
viewAttributeSourceFunction: viewAttributeSourceFunction || null,
128125
}),
129-
[
130-
enabledInspectedElementContextMenu,
131-
enabledInspectedElementContextMenuCopy,
132-
viewAttributeSourceFunction,
133-
],
126+
[enabledInspectedElementContextMenu, viewAttributeSourceFunction],
134127
);
135128

136129
useEffect(

packages/react-devtools-shared/src/devtools/views/context.js

-2
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,11 @@ StoreContext.displayName = 'StoreContext';
2323

2424
export type ContextMenuContextType = {|
2525
isEnabledForInspectedElement: boolean,
26-
supportsCopyOperation: boolean,
2726
viewAttributeSourceFunction?: ?ViewAttributeSource,
2827
|};
2928

3029
export const ContextMenuContext = createContext<ContextMenuContextType>({
3130
isEnabledForInspectedElement: false,
32-
supportsCopyOperation: false,
3331
viewAttributeSourceFunction: null,
3432
});
3533
ContextMenuContext.displayName = 'ContextMenuContext';

packages/react-devtools-shell/src/devtools.js

-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ inject('dist/app.js', () => {
5656
createElement(DevTools, {
5757
browserTheme: 'light',
5858
enabledInspectedElementContextMenu: true,
59-
enabledInspectedElementContextMenuCopy: true,
6059
showTabBar: true,
6160
warnIfLegacyBackendDetected: true,
6261
warnIfUnsupportedVersionDetected: true,

0 commit comments

Comments
 (0)