Firefox 57.0(Quantum) 에서 Greasemonkey(Userscript) 작동 안 되는 경우
Posted 2017. 11. 15. 20:29, Filed under: 개발/UserScript최근 Firefox 57.0 버전으로 업데이트 했는데, 몇몇 유저스크립트가 작동하지 않아서 확인해보니 아래 두가지가 문제였다.
1.Greasemonkey 4 확장기능은 57.0 에서 GM_setValue 함수를 지원하지 않는다.
GM_setValue 함수는 확장기능이 관리하는 저장소에 유저 설정, 캐시 데이터 등 값을 저장하기 위하여 쓰인다.
그런데 Greasemonkey 4 에서는 해당 함수를 지원하지 않는다고 한다. 정확히는 GM dot 함수로 바뀌었다.
Greasemonkey 4 Announcement (https://www.greasespot.net/2017/09/greasemonkey-4-for-script-authors.html)
위 문서를 참고해보니 기존의 GM_ 함수는 동기식이었고, 이것을 비동기식으로 바꾸기 위하여 작업을 한 결과가 GM dot 함수라고 한다. GM.setValue 처럼 GM 에 dot(.)을 붙인 함수의 형태로 쓴다는데, 그냥 함수만 바꾸면 되는 것은 아니고 사용법까지 달라지니 위 문서를 참조하는 것이 좋겠다. 제공되는 polyfill.js 를 이용하여 기존 유저스크립트 또는 다른 Userscript 엔진과도 호환성을 유지하는 방법도 나와있다.
async 와 await 에 대해서는 이 문서 에 예제가 잘 나와있다.
개발자 입장에서 근본적인 해결 방법은 코드 수정이겠지만, 만약 당신이 단순한 유저스크립트 사용자라면 Greasemonkey 확장기능의 사용 대신에 violentmonkey 확장기능을 사용하면 기존의 GM_setValue 함수를 지원하므로 간단히 해결할 수 있다.
2. 1번을 해결한 이후 나타난 문제는 exportFunction 함수가 undefined 라고 나오는 문제이다.
(exportFunction 함수를 어디에, 왜 사용하는지는 http://nomo.asia/340 를 참고)
Firefox 57.0 에서 지원하지 않는 것인지 아니면 Violentmonkey 에서 지원하지 않는 것인지는 확인해보지 않았다. 일단 위의 Greasemonkey 4 Announcement 문서에서는 unsafeWindow 보다 cloneInto and exportFunction 를 사용하라고 설명하고 있는 것 같은데 왜 안 되는지는 잘 모르겠다.
$(document).ready(function(){
unsafeWindow.fB = function() {
// 새로운 function 내용
console.log("fB was hijacked!");
};
})
출처: http://nomo.asia/340 [이름없음]
참고로 당시 상황은 아래와 같았다.
- Userscript 를 적용할 페이지에서 로드하는 js 파일 내에 fA, fB 라는 이름의 함수(function) 가 존재한다.
- fA 함수의 내부에서는 fB를 호출한다.
- 내가 Userscript를 이용하여 덮어씌우고 싶은(Override) 함수는 fB 함수이다.
Chrome 은 그냥 아래와 같이 하면 잘 됐었다.
$(document).ready(function(){ unsafeWindow.fB = function() { // 새로운 function 내용 console.log("fB was hijacked!"); }; })
Firefox 는 위와 같이 하면 안 돼서 아래와 같은 방법을 썼었다.
$(document).ready(function(){ newfB = function() { // 새로운 function 내용 console.log("fB was hijacked!"); }; unsafeWindow.fB = exportFunction (newfB, unsafeWindow); newfA = function() { newfB(); // fB 를 newfB로 대체한다. console.log("fA was hijacked!"); }; unsafeWindow.fA = exportFunction (newfA, unsafeWindow); })
$(document).ready(function(){
unsafeWindow.fB = function() {
// 새로운 function 내용
console.log("fB was hijacked!");
};
})
출처: http://nomo.asia/340 [이름없음]
Chrome 의 경우 별 문제가 없다. 아래와 같이 하면 문제 없이 작동한다. 내가 바꾸고싶은 함수는 fB 뿐이므로 fB의 내용만 바꿔주었다.
$(document).ready(function(){
unsafeWindow.fB = function() {
// 새로운 function 내용
console.log("fB was hijacked!");
};
})
run-at : document-start 조건을 추가하였으므로, document ready 내에 hijacking 코드를 추가해주어야 제대로 적용된다.
출처: http://nomo.asia/340 [이름없음]
$(document).ready(function(){
unsafeWindow.fB = function() {
// 새로운 function 내용
console.log("fB was hijacked!");
};
})
출처: http://nomo.asia/340 [이름없음]
$(document).ready(function(){
unsafeWindow.fB = function() {
// 새로운 function 내용
console.log("fB was hijacked!");
};
})
출처: http://nomo.asia/340 [이름없음]
해결 방법은, 그냥 Chrome 처럼 하면 잘 된다. 이게 Firefox 57.0 이라서 그런건지 Greasemonkey 와 Violentmonkey 의 차이인지는 모르겠지만, 또는 내 코드가 바뀌어서 그런건지는 모르겠지만 Chrome 의 경우처럼 하면 잘 된다. 다만 기존에 브라우저별 호환성을 위해 분기를 해놓았었는데 해당 부분을 아래와 같이 수정했다.
if( (web_browser === 'firefox') && (typeof exportFunction === 'function') ){ // Firefox 57.0 미만 & Greasemonkey 용 코드 } else { // Chrome 및 Firefox 57.0 이상 & Violentmonkey 용 코드 }
여전히 Firefox 57.0 미만 버전을 사용하는 사용자도 있을 수 있기 때문에, exportFunction 함수가 정의되어 있으면 기존 분기를 사용하도록 설정했다.