@@ -65,12 +65,6 @@ const generateUniqueMarkerID = () => {
6565 return `MARKER::${ u1 } ${ u2 } ` ;
6666} ;
6767
68- const enum xhrExtraCode {
69- INVALID_URL = 0x20 ,
70- DOMAIN_NOT_INCLUDED = 0x30 ,
71- DOMAIN_IN_BLACKLIST = 0x40 ,
72- }
73-
7468type OnBeforeSendHeadersOptions = `${chrome . webRequest . OnBeforeSendHeadersOptions } `;
7569type OnHeadersReceivedOptions = `${chrome . webRequest . OnHeadersReceivedOptions } `;
7670
@@ -283,7 +277,7 @@ export default class GMApi {
283277 }
284278
285279 @PermissionVerify . API ( {
286- confirm : async ( request : GMApiRequest < [ string , GMTypes . CookieDetails ] > , sender : IGetSender ) => {
280+ confirm : async ( request : GMApiRequest < [ string , GMTypes . CookieDetails ] > , sender : IGetSender , gmApi : GMApi ) => {
287281 if ( request . params [ 0 ] === "store" ) {
288282 return true ;
289283 }
@@ -299,6 +293,14 @@ export default class GMApi {
299293 url . hostname = detail . domain || "" ;
300294 }
301295 if ( getConnectMatched ( request . script . metadata . connect , url , sender ) === ConnectMatch . NONE ) {
296+ // 检查是否配置了权限
297+ const ret = await gmApi . permissionVerify . queryPermission ( request , {
298+ permission : "cookie" ,
299+ permissionValue : url . host ,
300+ } ) ;
301+ if ( ret && ret . allow ) {
302+ return true ;
303+ }
302304 throw new Error ( "hostname must be in the definition of connect" ) ;
303305 }
304306 const metadata : { [ key : string ] : string } = { } ;
@@ -689,18 +691,37 @@ export default class GMApi {
689691 }
690692
691693 @PermissionVerify . API ( {
692- confirm : async ( request : GMApiRequest < [ GMSend . XHRDetails ] > , sender : IGetSender , GMApiInstance : GMApi ) => {
693- const config = < GMSend . XHRDetails > request . params [ 0 ] ;
694+ confirm : async ( request : GMApiRequest < [ GMSend . XHRDetails ?] > , sender : IGetSender , GMApiInstance : GMApi ) => {
695+ const msgConn = sender . getConnect ( ) ;
696+ if ( ! msgConn ) {
697+ throw new Error ( "GM_xmlhttpRequest ERROR: msgConn is undefined" ) ;
698+ }
699+ const throwErrorFn = ( error : string ) => {
700+ msgConn . sendMessage ( {
701+ action : "onerror" ,
702+ data : {
703+ status : 0 ,
704+ responseHeaders : "" ,
705+ error : error ,
706+ readyState : 4 , // ERROR. DONE.
707+ } ,
708+ } ) ;
709+ return new Error ( error ) ;
710+ } ;
711+ const details = request . params [ 0 ] ;
712+ if ( ! details ) {
713+ throw throwErrorFn ( "param is failed" ) ;
714+ }
694715 let url ;
695716 try {
696- url = new URL ( config . url ) ;
717+ url = new URL ( details . url ) ;
697718 } catch {
698- request . extraCode = xhrExtraCode . INVALID_URL ;
699- return false ;
719+ const msg = `Refused to connect to " ${ details . url } ": The url is invalid` ;
720+ throw throwErrorFn ( msg ) ;
700721 }
701722 if ( GMApiInstance . gmExternalDependencies . isBlacklistNetwork ( url ) ) {
702- request . extraCode = xhrExtraCode . DOMAIN_IN_BLACKLIST ;
703- return false ;
723+ const msg = `Refused to connect to " ${ details . url } ": URL is blacklisted` ;
724+ throw throwErrorFn ( msg ) ;
704725 }
705726 const connectMatched = getConnectMatched ( request . script . metadata . connect , url , sender ) ;
706727 if ( connectMatched === ConnectMatch . ALL ) {
@@ -713,15 +734,24 @@ export default class GMApi {
713734 }
714735 // @connect 没有匹配,但有列明 @connect 的话,则自动拒绝
715736 if ( request . script . metadata . connect ?. find ( ( e ) => ! ! e ) ) {
716- request . extraCode = xhrExtraCode . DOMAIN_NOT_INCLUDED ;
717- return false ;
737+ // 查询数据库权限记录,如果之前用户允许过该域名,则放行,否则拒绝
738+ const ret = await GMApiInstance . permissionVerify . queryPermission ( request , {
739+ permission : "cors" ,
740+ permissionValue : url . hostname ,
741+ wildcard : true ,
742+ } ) ;
743+ if ( ret && ret . allow ) {
744+ return true ;
745+ }
746+ const msg = `Refused to connect to "${ details . url } ": This domain is not a part of the @connect list` ;
747+ throw throwErrorFn ( msg ) ;
718748 }
719749 // 其他情况:要询问用户
720750 }
721751 const metadata : { [ key : string ] : string } = { } ;
722752 metadata [ i18next . t ( "script_name" ) ] = i18nName ( request . script ) ;
723753 metadata [ i18next . t ( "request_domain" ) ] = url . hostname ;
724- metadata [ i18next . t ( "request_url" ) ] = config . url ;
754+ metadata [ i18next . t ( "request_url" ) ] = details . url ;
725755
726756 return {
727757 permission : "cors" ,
@@ -735,14 +765,12 @@ export default class GMApi {
735765 } ,
736766 alias : [ "GM.xmlHttpRequest" ] ,
737767 } )
738- async GM_xmlhttpRequest ( request : GMApiRequest < [ GMSend . XHRDetails ? ] > , sender : IGetSender ) {
768+ async GM_xmlhttpRequest ( request : GMApiRequest < [ GMSend . XHRDetails ] > , sender : IGetSender ) {
739769 if ( ! sender . isType ( GetSenderType . CONNECT ) ) {
740770 throw new Error ( "GM_xmlhttpRequest ERROR: sender is not MessageConnect" ) ;
741771 }
742- const msgConn = sender . getConnect ( ) ;
743- if ( ! msgConn ) {
744- throw new Error ( "GM_xmlhttpRequest ERROR: msgConn is undefined" ) ;
745- }
772+ const msgConn = sender . getConnect ( ) ! ;
773+
746774 let isConnDisconnected = false ;
747775 msgConn . onDisconnect ( ( ) => {
748776 isConnDisconnected = true ;
@@ -754,40 +782,8 @@ export default class GMApi {
754782
755783 const resultParam = new SWRequestResultParams ( markerID ) ;
756784
757- const throwErrorFn = ( error : string ) => {
758- if ( ! isConnDisconnected ) {
759- msgConn . sendMessage ( {
760- action : "onerror" ,
761- data : {
762- status : resultParam . statusCode ,
763- responseHeaders : resultParam . responseHeaders ,
764- error : `${ error } ` ,
765- readyState : 4 , // ERROR. DONE.
766- } ,
767- } ) ;
768- }
769- return new Error ( `${ error } ` ) ;
770- } ;
771-
772785 const details = request . params [ 0 ] ;
773- if ( ! details ) {
774- throw throwErrorFn ( "param is failed" ) ;
775- }
776786
777- if ( request . extraCode === xhrExtraCode . INVALID_URL ) {
778- const msg = `Refused to connect to "${ details . url } ": The url is invalid` ;
779- throw throwErrorFn ( msg ) ;
780- }
781- if ( request . extraCode === xhrExtraCode . DOMAIN_NOT_INCLUDED ) {
782- // 'Refused to connect to "https://nonexistent-domain-abcxyz.test/": This domain is not a part of the @connect list'
783- const msg = `Refused to connect to "${ details . url } ": This domain is not a part of the @connect list` ;
784- throw throwErrorFn ( msg ) ;
785- }
786- if ( request . extraCode === xhrExtraCode . DOMAIN_IN_BLACKLIST ) {
787- // 'Refused to connect to "https://example.org/": URL is blacklisted'
788- const msg = `Refused to connect to "${ details . url } ": URL is blacklisted` ;
789- throw throwErrorFn ( msg ) ;
790- }
791787 try {
792788 /*
793789 There are TM-specific parameters:
@@ -879,7 +875,19 @@ export default class GMApi {
879875 msgConn . onDisconnect ( offscreenCon . disconnect . bind ( offscreenCon ) ) ;
880876 }
881877 } catch ( e : any ) {
882- throw throwErrorFn ( `GM_xmlhttpRequest ERROR: ${ e ?. message || e || "Unknown Error" } ` ) ;
878+ const errorMsg = `GM_xmlhttpRequest ERROR: ${ e ?. message || e || "Unknown Error" } ` ;
879+ if ( ! isConnDisconnected ) {
880+ msgConn . sendMessage ( {
881+ action : "onerror" ,
882+ data : {
883+ status : resultParam . statusCode ,
884+ responseHeaders : resultParam . responseHeaders ,
885+ error : errorMsg ,
886+ readyState : 4 , // ERROR. DONE.
887+ } ,
888+ } ) ;
889+ }
890+ throw new Error ( errorMsg ) ;
883891 }
884892 }
885893
0 commit comments