@samitouri / QOS-React-2 / commits / 22ef96ae63

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.

Brian Vaughn committed Dec 29, 2019 at 13:27 UTC 22ef96ae63f40b1b9367bc2d8bdb3db33e6943b0
8 files changed +37 -23
packages/react-devtools-extensions/firefox/manifest.json
+1 -1
@@ -44,7 +44,7 @@
44 "scripts": ["build/background.js"]
45 },
46
47 - "permissions": ["file:///*", "http://*/*", "https://*/*"],
47 + "permissions": ["file:///*", "http://*/*", "https://*/*", "clipboardWrite"],
48
49 "content_scripts": [
50 {
packages/react-devtools-extensions/src/injectGlobalHook.js
+16
@@ -97,3 +97,19 @@ if (document.contentType === 'text/html') {
97 detectReact,
98 );
99 }
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
@@ -211,7 +211,6 @@ function createPanelIfReactLoaded() {
211 browserTheme: getBrowserTheme(),
212 componentsPortalContainer,
213 enabledInspectedElementContextMenu: true,
214 - enabledInspectedElementContextMenuCopy: isChrome,
214 overrideTab,
215 profilerPortalContainer,
216 showTabBar: false,
packages/react-devtools-shared/src/backend/utils.js
+13 -1
@@ -40,7 +40,19 @@ export function cleanForBridge(
40
41 export function copyToClipboard(value: any): void {
42 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 + }
56 }
57
58 export function copyWithSet(
packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.js
+6 -9
@@ -303,7 +303,6 @@ function InspectedElementView({
303
304 const {
305 isEnabledForInspectedElement,
306 - supportsCopyOperation,
306 viewAttributeSourceFunction,
307 } = useContext(ContextMenuContext);
308
@@ -445,14 +444,12 @@ function InspectedElementView({
444 <ContextMenu id="SelectedElement">
445 {data => (
446 <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>
453 <ContextMenuItem
454 onClick={() => storeAsGlobal(id, data.path)}
455 title="Store as global variable">
packages/react-devtools-shared/src/devtools/views/DevTools.js
+1 -8
@@ -54,7 +54,6 @@ export type Props = {|
54 canViewElementSourceFunction?: ?CanViewElementSource,
55 defaultTab?: TabID,
56 enabledInspectedElementContextMenu?: boolean,
57 - enabledInspectedElementContextMenuCopy?: boolean,
57 showTabBar?: boolean,
58 store: Store,
59 warnIfLegacyBackendDetected?: boolean,
@@ -97,7 +96,6 @@ export default function DevTools({
96 componentsPortalContainer,
97 defaultTab = 'components',
98 enabledInspectedElementContextMenu = false,
100 - enabledInspectedElementContextMenuCopy = false,
99 overrideTab,
100 profilerPortalContainer,
101 showTabBar = false,
@@ -123,14 +121,9 @@ export default function DevTools({
121 const contextMenu = useMemo(
122 () => ({
123 isEnabledForInspectedElement: enabledInspectedElementContextMenu,
126 - supportsCopyOperation: enabledInspectedElementContextMenuCopy,
124 viewAttributeSourceFunction: viewAttributeSourceFunction || null,
125 }),
129 - [
130 - enabledInspectedElementContextMenu,
131 - enabledInspectedElementContextMenuCopy,
132 - viewAttributeSourceFunction,
133 - ],
126 + [enabledInspectedElementContextMenu, viewAttributeSourceFunction],
127 );
128
129 useEffect(
packages/react-devtools-shared/src/devtools/views/context.js
-2
@@ -23,13 +23,11 @@ StoreContext.displayName = 'StoreContext';
23
24 export type ContextMenuContextType = {|
25 isEnabledForInspectedElement: boolean,
26 - supportsCopyOperation: boolean,
26 viewAttributeSourceFunction?: ?ViewAttributeSource,
27 |};
28
29 export const ContextMenuContext = createContext<ContextMenuContextType>({
30 isEnabledForInspectedElement: false,
32 - supportsCopyOperation: false,
31 viewAttributeSourceFunction: null,
32 });
33 ContextMenuContext.displayName = 'ContextMenuContext';
packages/react-devtools-shell/src/devtools.js
-1
@@ -56,7 +56,6 @@ inject('dist/app.js', () => {
56 createElement(DevTools, {
57 browserTheme: 'light',
58 enabledInspectedElementContextMenu: true,
59 - enabledInspectedElementContextMenuCopy: true,
59 showTabBar: true,
60 warnIfLegacyBackendDetected: true,
61 warnIfUnsupportedVersionDetected: true,