Right Click & Copy Enabler
A Chrome extension that re-enables right-click and text copying on websites that block them.
What makes it good
- 1Re-enables the right-click context menu on restricted sites
- 2Restores text selection and copying
- 3Lightweight and instant
How it works
How it works
Sites block right-click and selection in several unrelated ways, so undoing it takes four layers rather than one trick. The script runs at document_start in the page's MAIN world, which is the only place it can see and rewrite the site's own event wiring.
chrome.scripting.registerContentScripts([{
id: 'rcce-unblock',
js: ['unblock.js'],
matches,
runAt: 'document_start',
world: 'MAIN', // needs the page's real globals, not an isolated copy
allFrames: true,
persistAcrossSessions: true,
}]);1. Refuse new blockers
Patching addEventListener stops page-wide handlers from ever attaching. Listeners on a specific element are left alone, so custom menus and editors keep working.
const nativeAdd = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function (type, listener, options) {
if (BLOCKED.has(type) && isGlobalTarget(this)) return;
return nativeAdd.call(this, type, listener, options);
};2. Neutralise the ones already attached
Layer 1 only helps if the extension runs first. Patching preventDefault works retroactively, which is what makes turning the extension on mid-page take effect without a reload:
const native = Event.prototype.preventDefault;
Event.prototype.preventDefault = function () {
if (BLOCKED.has(this.type)) return; // the blocker's call becomes a no-op
return native.call(this);
};3. Outrank document-level handlers
Most blockers listen on document. A capture listener on window runs *before* those, because window is the ancestor — so cutting propagation there stops them. Listening on document.body instead, as the first version did, is too late: body is a descendant, and its capture phase runs after document has already handled the event.
for (const type of BLOCKED) {
nativeAdd.call(window, type, (e) => e.stopPropagation(), true);
}4. Undo the CSS and the inline attributes
user-select: none, oncontextmenu="return false" and unselectable are all stripped, with a MutationObserver for single-page apps that re-add them after navigation.
Scope
Enabling it everywhere would break legitimate custom context menus, so it is a three-way choice — off, this site, or everywhere — and <all_urls> is requested only if you pick the last one.