1
1
// ==UserScript==
2
2
// @name JS Cookie Monitor/Debugger Hook
3
3
// @namespace https://github.com/CC11001100/js-cookie-monitor-debugger-hook
4
- // @version 0.9
4
+ // @version 0.10
5
5
// @description 用于监控js对cookie的修改,或者在cookie符合给定条件时进入断点
6
6
// @document https://github.com/CC11001100/js-cookie-monitor-debugger-hook
7
7
// @author CC11001100
21
21
22
22
// 设置事件断点是否开启,一般保持默认即可
23
23
const enableEventDebugger = {
24
- "add" : true ,
25
- "update" : true ,
26
- "delete" : true ,
27
- "read" : true ,
24
+ "add" : true , "update" : true , "delete" : true , "read" : true ,
28
25
}
29
26
30
27
// 在控制台打印日志时字体大小,根据自己喜好调整
34
31
// 使用document.cookie更新cookie,但是cookie新的值和原来的值一样,此时要不要忽略这个事件
35
32
const ignoreUpdateButNotChanged = false ;
36
33
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
+
37
97
// 此处实现的反复hook,保证页面流程能够继续往下走下去
38
98
( function addCookieHook ( ) {
39
- Object . defineProperty ( document , "cookie" , {
99
+ const handler = {
40
100
get : ( ) => {
101
+
102
+ // 先恢复原状
41
103
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
+ // 先触发相关的事件
47
122
cc11001100_onSetCookie ( newValue ) ;
123
+
124
+ // 然后恢复原状,把我们设置的hook啥的下掉
48
125
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 ) ;
54
147
} ) ( ) ;
55
148
56
149
/**
88
181
89
182
const message = [
90
183
91
- normalStyle ,
92
- now ( ) ,
184
+ normalStyle , now ( ) ,
93
185
94
- normalStyle ,
95
- "JS Cookie Monitor: " ,
186
+ normalStyle , "JS Cookie Monitor: " ,
96
187
97
- normalStyle ,
98
- "delete cookie, cookieName = " ,
188
+ normalStyle , "delete cookie, cookieName = " ,
99
189
100
- valueStyle ,
101
- `${ cookieName } ` ,
190
+ valueStyle , `${ cookieName } ` ,
102
191
103
192
...( ( ) => {
104
193
if ( ! cookieValue ) {
105
194
return [ ] ;
106
195
}
107
- return [
108
- normalStyle ,
109
- ", value = " ,
196
+ return [ normalStyle , ", value = " ,
110
197
111
- valueStyle ,
112
- `${ cookieValue } ` ,
113
- ] ;
198
+ valueStyle , `${ cookieValue } ` , ] ;
114
199
} ) ( ) ,
115
200
116
- normalStyle ,
117
- `, code location = ${ getCodeLocation ( ) } `
118
- ] ;
201
+ normalStyle , `, code location = ${ getCodeLocation ( ) } ` ] ;
119
202
console . log ( genFormatArray ( message ) , ...message ) ;
120
203
121
204
testDebuggerRules ( cookieOriginalValue , "delete" , cookieName , cookieValue ) ;
134
217
135
218
const message = [
136
219
137
- normalStyle ,
138
- now ( ) ,
220
+ normalStyle , now ( ) ,
139
221
140
- normalStyle ,
141
- "JS Cookie Monitor: " ,
222
+ normalStyle , "JS Cookie Monitor: " ,
142
223
143
- normalStyle ,
144
- "update cookie, cookieName = " ,
224
+ normalStyle , "update cookie, cookieName = " ,
145
225
146
- valueStyle ,
147
- `${ cookieName } ` ,
226
+ valueStyle , `${ cookieName } ` ,
148
227
149
228
...( ( ) => {
150
229
if ( cookieValueChanged ) {
151
- return [
152
- normalStyle ,
153
- `, oldValue = ` ,
230
+ return [ normalStyle , `, oldValue = ` ,
154
231
155
- valueStyle ,
156
- `${ oldCookieValue } ` ,
232
+ valueStyle , `${ oldCookieValue } ` ,
157
233
158
- normalStyle ,
159
- `, newValue = ` ,
234
+ normalStyle , `, newValue = ` ,
160
235
161
- valueStyle ,
162
- `${ newCookieValue } `
163
- ]
236
+ valueStyle , `${ newCookieValue } ` ]
164
237
} else {
165
- return [
166
- normalStyle ,
167
- `, value = ` ,
238
+ return [ normalStyle , `, value = ` ,
168
239
169
- valueStyle ,
170
- `${ newCookieValue } ` ,
171
- ] ;
240
+ valueStyle , `${ newCookieValue } ` , ] ;
172
241
}
173
242
} ) ( ) ,
174
243
175
- normalStyle ,
176
- `, valueChanged = ` ,
244
+ normalStyle , `, valueChanged = ` ,
177
245
178
- valueStyle ,
179
- `${ cookieValueChanged } ` ,
246
+ valueStyle , `${ cookieValueChanged } ` ,
180
247
181
- normalStyle ,
182
- `, code location = ${ getCodeLocation ( ) } `
183
- ] ;
248
+ normalStyle , `, code location = ${ getCodeLocation ( ) } ` ] ;
184
249
console . log ( genFormatArray ( message ) , ...message ) ;
185
250
186
251
testDebuggerRules ( cookieOriginalValue , "update" , cookieName , newCookieValue , cookieValueChanged ) ;
192
257
193
258
const message = [
194
259
195
- normalStyle ,
196
- now ( ) ,
260
+ normalStyle , now ( ) ,
197
261
198
- normalStyle ,
199
- "JS Cookie Monitor: " ,
262
+ normalStyle , "JS Cookie Monitor: " ,
200
263
201
- normalStyle ,
202
- "add cookie, cookieName = " ,
264
+ normalStyle , "add cookie, cookieName = " ,
203
265
204
- valueStyle ,
205
- `${ cookieName } ` ,
266
+ valueStyle , `${ cookieName } ` ,
206
267
207
- normalStyle ,
208
- ", cookieValue = " ,
268
+ normalStyle , ", cookieValue = " ,
209
269
210
- valueStyle ,
211
- `${ cookieValue } ` ,
270
+ valueStyle , `${ cookieValue } ` ,
212
271
213
- normalStyle ,
214
- `, code location = ${ getCodeLocation ( ) } `
215
- ] ;
272
+ normalStyle , `, code location = ${ getCodeLocation ( ) } ` ] ;
216
273
console . log ( genFormatArray ( message ) , ...message ) ;
217
274
218
275
testDebuggerRules ( cookieOriginalValue , "add" , cookieName , cookieValue ) ;
281
338
}
282
339
283
340
return {
284
- key,
285
- value
341
+ key, value
286
342
}
287
343
}
288
344
469
525
470
526
}
471
527
472
- ) ( ) ;
528
+ ) ( ) ;
0 commit comments