Chrome Extension MV3에서 commands를 선별적으로 활성화 할 수 있을까?

DoDoBest

·

2023. 4. 10. 22:19

 결론: 현재로서는 불가능합니다.

 

https://chrome.google.com/webstore/detail/%EB%8B%B9%EA%B7%BC%EB%82%98%EB%9D%BC/efdhlhlgcmepgdejhbnkegfgikopifnm?hl=ko 

 

당근나라

네이버 카페에서 게시물 숨기기를 도와줍니다.

chrome.google.com

 네이버 카페에서 특정 등급이나 등록한 사용자의 게시물을 숨기는 확장 프로그램입니다. 네이버 카페는 InnerFrame에서 게시물을 보여주기 때문에, 관심있는 판매글을 북마크하려면 판매글의 주소를 직접 복사해서 등록해야 합니다. 이 과정을 단축키로 수행할 수 있도록 기능을 추가했습니다.

 그러나 Ctrl+B와 같은 단축키가 다른 사이트에서 이미 설정되어 있을 경우, 해당 사이트의 단축키가 동작하지 않는 문제가 발생합니다.

 따라서, 네이버 카페가 아닌 곳에서 단축키를 입력할 경우, 북마크 기능 대신 해당 사이트의 단축키를 동작하도록 수정해야 합니다. 이를 위해 자바스크립트 코드로 입력된 단축키와 동일한 효과를 주는 방식을 생각해보았습니다.

 

1. dispatchEvent 활용하기

 아래는 구현한 코드입니다. 코드는 에러 없이 정상적으로 실행되지만, 키보드 입력 효과가 나타나지는 않았습니다. 

function handleShortCut(shortCut) {
    function parseShortcut(shortcutString) {
        const parts = shortcutString.split('+');
        return {
            key: parts.pop().toUpperCase(),
            ctrlKey: parts.includes('Ctrl'),
            shiftKey: parts.includes('Shift'),
            altKey: parts.includes('Alt'),
            metaKey: parts.includes('Cmd') || parts.includes('Meta'),
        };
    }

    const { key, ctrlKey, shiftKey, altKey, metaKey } = parseShortcut(shortCut);

    document.dispatchEvent(
        new KeyboardEvent('keydown', {
            key,
            ctrlKey,
            shiftKey,
            altKey,
            metaKey,
        })
    );
}

chrome.commands.onCommand.addListener((command) => {
    if (command.toString() === 'add-bookmark') {
        addBookMark(null, true).then(function (result) {
            if (result !== false) {
                return;
            }
            chrome.commands.getAll((commands) => {
                const commandKey = commands.find((cmd) => cmd.name === command.toString())?.shortcut;
                if (!commandKey) {
                    return;
                }
                chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {

                    // 1. document.dispatchEvent
                    chrome.scripting.executeScript({
                        target: {tabId: tabs[0].id, frameIds: [0]},
                        func: handleShortCut,
                        args: [commandKey],
                    });
                });
            });
        });
    }
});

 

관련 참고 자료

https://stackoverflow.com/questions/45412590/sending-keyboard-events-programmatically-doesnt-dispatch-them-into-inputs

 

Sending keyboard events programmatically doesn't dispatch them into inputs

I am sending programmatically generated keyboard events to the document. I was hoping that the currently focused input element would display them, however it doesn't. The events are generated from a

stackoverflow.com

2. chrome.debugger

https://stackoverflow.com/a/34722970

 

How to to initialize keyboard event with given char/keycode in a Chrome extension?

I'm developing a Google Chrome extension which simulates keyboard events on a web-page. I found that event.initKeyboardEvent() does not work properly because of this webkit bug and I also found s...

stackoverflow.com

 위 답변을 참고하여, chrome.debugger를 사용하여 아래와 같이 코드를 구현하였습니다. 그러나 이 코드도 아무런 효과가 나타나지 않았습니다. 만약 효과가 있다고 하더라도, 디버깅 중임을 나타내는 상단 안내창이 뜨고 몇 초의 시간이 소요되어사용하기 어려울 것 같습니다. 빠른 확인을 위해 Ctrl+B를 하드코딩하여 동작하도록 설정했습니다.

chrome.commands.onCommand.addListener((command) => {
    if (command.toString() === 'add-bookmark') {
        addBookMark(null, true).then(function (result) {
            if (result !== false) {
                return;
            }
            chrome.commands.getAll((commands) => {
                const commandKey = commands.find((cmd) => cmd.name === command.toString())?.shortcut;
                if (!commandKey) {
                    return;
                }
                chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {

                    chrome.debugger.attach({ tabId: tabs[0].id }, "1.0").then(function() {
                        chrome.debugger.sendCommand({tabId: tabs[0].id}, 'Input.dispatchKeyEvent', {
                            type: 'rawKeyDown',
                            windowsVirtualKeyCode: 0x11,
                            nativeVirtualKeyCode: 0x11,
                        }).then(function() {
                            chrome.debugger.sendCommand({tabId: tabs[0].id}, 'Input.dispatchKeyEvent', {
                                type: 'rawKeyDown',
                                windowsVirtualKeyCode: 0x42,
                                nativeVirtualKeyCode: 0x42,
                            }).then(function() {
                                chrome.debugger.detach({ tabId: tabs[0].id });
                            });
                        });
                    })
                });
            });
        });
    }
});

chrome.debugger의 arguments 관련 정보

https://chromedevtools.github.io/devtools-protocol/tot/Input/

 

Chrome DevTools Protocol

Chrome DevTools Protocol - version tot - Input domain

chromedevtools.github.io

windowVirtualKeyCode 정보

https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes

 

Virtual-Key Codes (Winuser.h) - Win32 apps

The following table shows the symbolic constant names, hexadecimal values, and mouse or keyboard equivalents for the virtual-key codes used by the system. The codes are listed in numeric order.

learn.microsoft.com

 

ChatGPT 답변

 GPT 3.5와 GPT 4.0 모두 1번 dispatchEvent 함수를 사용하는 방법을 알려줬습니다. GPT 3.5는 알려준 방법이 작동하지 않는 다는 질문에 약간 다른 코드를 계속 알려주다가 마지막에는 2개의 답변을 번갈아가며 알려줬습니다.

 하지만 GPT 4.0에서는 안 된다는 계속된 질문에 아래와 같이 답변했습니다.

'ChatGPT와 학습하기' 카테고리의 다른 글

HashTable과 HashMap  (0) 2023.03.06
ArrayList와 LinkedList  (0) 2023.02.20