theme: cyanosis
Background: one of our systems has a function to prohibit copying. If there is no permission to copy, a toast will pop up when copying. It's essentially a document oncopy = () => { ... }. One day, a user reported that as soon as she entered the page, she would pop up a toast that was forbidden to copy, and it would pop up every time she moved, so the system could not be used at all
On site reproduction
The user just said a few words. Everyone said it was incredible and impossible. Finally, when sharing the screen, if so, it makes people doubt life. Once the text is selected with the mouse, the page will pop up and cannot be copied. It is probably as follows:
copy will be triggered if text is selected without manual copying
The recording screen at that time could not be made public because of confidentiality. The general situation is like this. The above is the screen where I know how to reproduce my local demo record. Next, I will gradually repeat the problem troubleshooting process from the perspective of a third party in the same way
Remote control troubleshooting
First, open the console and put document Copy rewrite
const cp = document.oncopy.bind(document); document.oncopy = () => { console.log(1); cp(); return false; }
As a result, it was found that the toast and print 1 really popped up after selecting it
Next, a breakpoint is added, which will still trigger. The same process seems to make no difference. So, I began to doubt the user's plug-ins, glanced at them, there were no suspicious plug-ins, and then turned off all her Chrome extensions, which will still reappear
Preliminary conclusion: the triggering of oncopy behavior has nothing to do with the plug-in
At this time, I think of a sentence: 90% can be solved by restarting, 9% can be solved by reinstalling, and 1% can only be solved by buying a new computer
The computer restarted and continued remote control. It's the same problem. I said, why don't you open other websites? Any website is ok. I'll show you all the pages patiently. So I tried a few pages at random, opened the console, entered oncopy, and then immediately reproduced the problem:
document.oncopy = () => { console.log(1); return false; }
"You see, all the pages have the same problem - you can try a few more pages at will" - in fact, I'm checking the information to see if there is something outside my knowledge blind spot
Step 2 Conclusion: any page will have problems, so the root of the problem is not at the page level, but at a higher level
No similar problems were found in the data. I probably watched her operate for a few minutes reluctantly. I didn't say a word and was in a daze at the computer. An idea suddenly occurred: personalized settings on the system
check the input method, Sogou. It should have no impact. However, in the frequent operations of the other party, a faint small logo attracted my attention
🧑🔧: "I found that you have a small logo here. What's it for?"
👩🦰: "A translation tool"
🧑🔧: "Move more, I want to see more clearly"
👩🦰: "You see, put it here and it will translate the words on the screen"
🧑🔧: "Then you try to translate other software such as ppt"
👩🦰: "It's OK"
🧑🔧: "Then turn off the translation software and come back to the page."
👩🦰: "It seems no problem"
🧑🔧: "Well, that's the problem with this software. I think there is a function of automatically translating the English where your mouse is located. The implementation of this function may be: when you put your mouse on the English, it will trigger the copy event of the system, which may help you copy directly or press the button behind your back. Open this application again and turn off this function first."
👩🦰: "Oh, I see. There is a function of word delimitation search, which should be related to him."
After turning it off, the problem is solved, or I'm curious: what's the name of your software? I'll download it to play
The real culprit is the European dictionary, which will automatically trigger copying when you select the text, and get the English copy to search for the information of that word - cross word search as the name suggests
Download to play
After downloading and opening it, I wrote a simple demo myself, and it all reappeared
const C: React.FC = () => { const ref = React.useRef<HTMLDivElement>(null); React.useEffect(() => { document.oncopy = (): boolean => { Toast.error('Prohibit copying');// Just a toast, just find a ui library return false; }; document.onclick = (): void => { ref.current!.innerHTML += 'You clicked on the page<br />'; }; const handleKeydown = (e): void => { ref.current!.innerHTML += `You pressed ${e.key}<br />`; }; document.addEventListener('keydown', handleKeydown); return (): void => { document.oncopy = null; document.onclick = null; document.removeEventListener('keydown', handleKeydown); }; }, []); return ( <> <pre> I say you are the April day on earth; Laughter lit up the four winds; Qingling dances and changes in the brilliance of spring. You are the clouds and smoke in the early days of April, At dusk, the wind is blowing soft, the stars are inadvertently flashing, and the drizzle is sprinkled in front of the flowers. </pre> <div> Operation record <div ref={ref} /> </div> </> ); };
As expected, if we do not open the European dictionary, if we copy the contents of the page, a toast will pop up to prohibit copying, as follows:
European dictionary has been opened, which is shown as follows:
Therefore, the problem is how to distinguish the copy of European dictionary
Solution
We use the simplest method. When you press command(key is Meta) and it doesn't pop up, the production key queue. When the last press is c, the consumer producer queue will search forward for whether you have pressed command
const Cpn: React.FC = () => { const ref = React.useRef<HTMLDivElement>(null); const providerQuene = React.useRef<string[]>([]); const triggerCopy = React.useCallback(() => { // Consumer producer queue data const last = providerQuene.current.pop(); // If you press c last and the keyboard doesn't pop up, look forward to see if you pressed command if (last === 'c' && providerQuene.current.includes('Meta')) { Toast.error('Prohibit copying'); } }, [providerQuene]); React.useEffect(() => { document.oncopy = (): boolean => { triggerCopy(); return false; }; document.onclick = (): void => { ref.current!.innerHTML += 'You clicked on the page<br />'; }; const handleKeydown = (e: KeyboardEvent): void => { if (e.key === 'Meta') { providerQuene.current.push('Meta'); } if (e.key === 'c') { providerQuene.current.push('c'); } ref.current!.innerHTML += `You pressed ${e.key}<br />`; }; const handleKeyUp = ({ key }: KeyboardEvent): void => { key === 'Meta' && (providerQuene.current = []); // The meta key pops up and clears the producer queue }; document.addEventListener('keydown', handleKeydown); document.addEventListener('keyup', handleKeyUp); return (): void => { document.oncopy = null; document.onclick = null; document.removeEventListener('keydown', handleKeydown); document.removeEventListener('keyup', handleKeyUp); }; }, []); return ( <> <pre> I say you are the April day on earth; Laughter lit up the four winds; Dancing in spring. You are the clouds and smoke in the early days of April, At dusk, the wind is blowing soft, the stars are inadvertently flashing, and the drizzle is sprinkled in front of the flowers. </pre> <div> Operation record <div ref={ref} /> </div> </> ); };
All the above operations are under the Chrome browser of mac. safari seems to be OK. The compatibility problems of other browsers or windows can be handled in a similar way