11// ==UserScript==
22// @name JS Cookie Monitor/Debugger Hook
33// @namespace https://github.com/CC11001100/js-cookie-monitor-debugger-hook
4- // @version 0.9
4+ // @version 0.10
55// @description 用于监控js对cookie的修改,或者在cookie符合给定条件时进入断点
66// @document https://github.com/CC11001100/js-cookie-monitor-debugger-hook
77// @author CC11001100
2121
2222 // 设置事件断点是否开启,一般保持默认即可
2323 const enableEventDebugger = {
24- "add" : true ,
25- "update" : true ,
26- "delete" : true ,
27- "read" : true ,
24+ "add" : true , "update" : true , "delete" : true , "read" : true ,
2825 }
2926
3027 // 在控制台打印日志时字体大小,根据自己喜好调整
3431 // 使用document.cookie更新cookie,但是cookie新的值和原来的值一样,此时要不要忽略这个事件
3532 const ignoreUpdateButNotChanged = false ;
3633
34+ // 网站的开发者也可能会使用到Object.,这会与工具内置的冲突,使用这个变量持有者目标网站开发者自己设置的
35+ // 然后在执行的时候使其真正的生效,这样不影响原有的逻辑
36+ let realDocumentCookieProperty = null ;
37+
38+ // 用于区分是本插件自己调用的definePropertyIsMe还是外部调用的
39+ const definePropertyIsMe = "CC11001100-js-cookie-monitor-debugger-hook" ;
40+
41+ // 页面内部的Object.defineProperty需要能够劫持一下
42+ ( function ( ) {
43+
44+ // 把Object.defineProperty给拦截了
45+ Object . defineProperty = new Proxy ( Object . defineProperty , {
46+ apply : function ( target , thisArg , argArray ) {
47+
48+ // 检查是否是自己调用的
49+ const isMe = argArray && argArray . length >= 3 && argArray [ 2 ] && definePropertyIsMe in argArray [ 2 ] ;
50+
51+ // 检查是否是定义的document.cookie
52+ const isDocumentCookie = argArray && argArray . length >= 2 && argArray [ 0 ] === document && "cookie" === argArray [ 1 ] ;
53+
54+ if ( ! isMe && isDocumentCookie ) {
55+ // 检查要定义访问符的是否是document.cookie这个方法的话就包装一下,保证同时多个都能被调用到
56+ if ( argArray && argArray . length >= 3 ) {
57+ // 更新一下real property就不管了,
58+ realDocumentCookieProperty = argArray [ 2 ] ;
59+ return ;
60+ }
61+ }
62+ return target . apply ( thisArg , argArray ) ;
63+ }
64+ } ) ;
65+
66+ Object . defineProperty . toString = function ( ) {
67+ return "function defineProperty() { [native code] }" ;
68+ }
69+
70+ // 把Object.defineProperties也给拦截了
71+ Object . defineProperties = new Proxy ( Object . defineProperties , {
72+ apply : function ( target , thisArg , argArray ) {
73+ // 可能会通过如下代码来调用:
74+ // Object.defineProperties(document, {"cookie": {...})
75+ const isDocumentCookie = argArray && argArray . length >= 2 && document === argArray [ 0 ] && "cookie" in argArray [ 1 ] ;
76+ if ( isDocumentCookie ) {
77+ // 把要设置的property描述符持有者
78+ realDocumentCookieProperty = argArray [ 1 ] [ "cookie" ] ;
79+ // 任务这个cookie的define已经执行完了,将其删除掉
80+ delete argArray [ 1 ] [ "cookie" ] ;
81+ // 如果只有一个cookie的话,删除完没有其它的属性了,则没必要继续往下了
82+ // 如果有剩余的属性的话,则需要原样继续执行
83+ if ( ! Object . keys ( argArray [ 1 ] ) . length ) {
84+ return ;
85+ }
86+ }
87+ return target . apply ( thisArg , argArray ) ;
88+ }
89+ } ) ;
90+
91+ Object . defineProperties . toString = function ( ) {
92+ return "function defineProperties() { [native code] }" ;
93+ }
94+
95+ } ) ( ) ;
96+
3797 // 此处实现的反复hook,保证页面流程能够继续往下走下去
3898 ( function addCookieHook ( ) {
39- Object . defineProperty ( document , "cookie" , {
99+ const handler = {
40100 get : ( ) => {
101+
102+ // 先恢复原状
41103 delete document . cookie ;
42- const currentDocumentCookie = document . cookie ;
43- addCookieHook ( ) ;
44- return currentDocumentCookie ;
45- } ,
46- set : newValue => {
104+
105+ try {
106+ // 如果网站开发者有设置自己的属性访问符的话,则以他设置的为准,把它的返回值作为此函数最终的返回值,保持其原有逻辑
107+ if ( realDocumentCookieProperty && "get" in realDocumentCookieProperty ) {
108+ // 在网站执行者自己定义的cookie的property执行期间,我们的工具添加的hook是被下掉的,所以是没有影响的
109+ return realDocumentCookieProperty [ "get" ] . apply ( this , arguments ) ;
110+ } else {
111+ // 如果网站开发者没有设置自己的property的话,则获取到真正的cookie值返回
112+ return document . cookie ;
113+ }
114+ } finally {
115+ // 然后这么获取完之后,还是要把hook加上
116+ addCookieHook ( ) ;
117+ }
118+
119+ } , set : newValue => {
120+
121+ // 先触发相关的事件
47122 cc11001100_onSetCookie ( newValue ) ;
123+
124+ // 然后恢复原状,把我们设置的hook啥的下掉
48125 delete document . cookie ;
49- document . cookie = newValue ;
50- addCookieHook ( ) ;
51- } ,
52- configurable : true
53- } ) ;
126+
127+ try {
128+ // 如果网站开发者有设置自己的属性访问符的话,则以他设置的为准
129+ if ( realDocumentCookieProperty && "set" in realDocumentCookieProperty ) {
130+ // 在网站执行者自己定义的cookie的property执行期间,我们的工具添加的hook是被下掉的,所以是没有影响的
131+ // 不过这同时带来一个新的问题,就是如果它在这个property中进行cookie的操作我们无法感知到,那能怎么办呢?有得必有失
132+ // TODO 2023-7-26 22:02:11 那,有没有比较简单的“我全都要”的方案呢?
133+ realDocumentCookieProperty [ "set" ] . apply ( this , [ newValue ] ) ;
134+ } else {
135+ // 如果网站开发者没有设置property或者没有设置set的话,则还是走默认的赋值逻辑
136+ document . cookie = newValue ;
137+ }
138+ } finally {
139+ // 然后再把hook设置上,加在finally里保证就算出错了也能恢复hook
140+ addCookieHook ( ) ;
141+ }
142+
143+ } , configurable : true , enumerable : false ,
144+ } ;
145+ handler [ definePropertyIsMe ] = true ;
146+ Object . defineProperty ( document , "cookie" , handler ) ;
54147 } ) ( ) ;
55148
56149 /**
88181
89182 const message = [
90183
91- normalStyle ,
92- now ( ) ,
184+ normalStyle , now ( ) ,
93185
94- normalStyle ,
95- "JS Cookie Monitor: " ,
186+ normalStyle , "JS Cookie Monitor: " ,
96187
97- normalStyle ,
98- "delete cookie, cookieName = " ,
188+ normalStyle , "delete cookie, cookieName = " ,
99189
100- valueStyle ,
101- `${ cookieName } ` ,
190+ valueStyle , `${ cookieName } ` ,
102191
103192 ...( ( ) => {
104193 if ( ! cookieValue ) {
105194 return [ ] ;
106195 }
107- return [
108- normalStyle ,
109- ", value = " ,
196+ return [ normalStyle , ", value = " ,
110197
111- valueStyle ,
112- `${ cookieValue } ` ,
113- ] ;
198+ valueStyle , `${ cookieValue } ` , ] ;
114199 } ) ( ) ,
115200
116- normalStyle ,
117- `, code location = ${ getCodeLocation ( ) } `
118- ] ;
201+ normalStyle , `, code location = ${ getCodeLocation ( ) } ` ] ;
119202 console . log ( genFormatArray ( message ) , ...message ) ;
120203
121204 testDebuggerRules ( cookieOriginalValue , "delete" , cookieName , cookieValue ) ;
134217
135218 const message = [
136219
137- normalStyle ,
138- now ( ) ,
220+ normalStyle , now ( ) ,
139221
140- normalStyle ,
141- "JS Cookie Monitor: " ,
222+ normalStyle , "JS Cookie Monitor: " ,
142223
143- normalStyle ,
144- "update cookie, cookieName = " ,
224+ normalStyle , "update cookie, cookieName = " ,
145225
146- valueStyle ,
147- `${ cookieName } ` ,
226+ valueStyle , `${ cookieName } ` ,
148227
149228 ...( ( ) => {
150229 if ( cookieValueChanged ) {
151- return [
152- normalStyle ,
153- `, oldValue = ` ,
230+ return [ normalStyle , `, oldValue = ` ,
154231
155- valueStyle ,
156- `${ oldCookieValue } ` ,
232+ valueStyle , `${ oldCookieValue } ` ,
157233
158- normalStyle ,
159- `, newValue = ` ,
234+ normalStyle , `, newValue = ` ,
160235
161- valueStyle ,
162- `${ newCookieValue } `
163- ]
236+ valueStyle , `${ newCookieValue } ` ]
164237 } else {
165- return [
166- normalStyle ,
167- `, value = ` ,
238+ return [ normalStyle , `, value = ` ,
168239
169- valueStyle ,
170- `${ newCookieValue } ` ,
171- ] ;
240+ valueStyle , `${ newCookieValue } ` , ] ;
172241 }
173242 } ) ( ) ,
174243
175- normalStyle ,
176- `, valueChanged = ` ,
244+ normalStyle , `, valueChanged = ` ,
177245
178- valueStyle ,
179- `${ cookieValueChanged } ` ,
246+ valueStyle , `${ cookieValueChanged } ` ,
180247
181- normalStyle ,
182- `, code location = ${ getCodeLocation ( ) } `
183- ] ;
248+ normalStyle , `, code location = ${ getCodeLocation ( ) } ` ] ;
184249 console . log ( genFormatArray ( message ) , ...message ) ;
185250
186251 testDebuggerRules ( cookieOriginalValue , "update" , cookieName , newCookieValue , cookieValueChanged ) ;
192257
193258 const message = [
194259
195- normalStyle ,
196- now ( ) ,
260+ normalStyle , now ( ) ,
197261
198- normalStyle ,
199- "JS Cookie Monitor: " ,
262+ normalStyle , "JS Cookie Monitor: " ,
200263
201- normalStyle ,
202- "add cookie, cookieName = " ,
264+ normalStyle , "add cookie, cookieName = " ,
203265
204- valueStyle ,
205- `${ cookieName } ` ,
266+ valueStyle , `${ cookieName } ` ,
206267
207- normalStyle ,
208- ", cookieValue = " ,
268+ normalStyle , ", cookieValue = " ,
209269
210- valueStyle ,
211- `${ cookieValue } ` ,
270+ valueStyle , `${ cookieValue } ` ,
212271
213- normalStyle ,
214- `, code location = ${ getCodeLocation ( ) } `
215- ] ;
272+ normalStyle , `, code location = ${ getCodeLocation ( ) } ` ] ;
216273 console . log ( genFormatArray ( message ) , ...message ) ;
217274
218275 testDebuggerRules ( cookieOriginalValue , "add" , cookieName , cookieValue ) ;
281338 }
282339
283340 return {
284- key,
285- value
341+ key, value
286342 }
287343 }
288344
469525
470526 }
471527
472- ) ( ) ;
528+ ) ( ) ;
0 commit comments