Переглянути джерело

redesigned GM_xmlhttpRequest, added finalUrl support, fixed #10

Signed-off-by: Gerald <[email protected]>
Gerald 11 роки тому
батько
коміт
6fefc1f061
3 змінених файлів з 122 додано та 101 видалено
  1. 109 11
      background.js
  2. 12 89
      injected.js
  3. 1 1
      manifest.json

+ 109 - 11
background.js

@@ -1,4 +1,18 @@
 var db,port=null,pos=0;
+function getUniqId() {
+	function int2str(i) {
+		var k='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_+',
+				s='',m;
+		while(i>0) {
+			m=i%64;
+			s+=k[m];
+			i=Math.floor(i/64);
+		}
+		return s;
+	}
+	return int2str(Date.now()%0x80000*0x100+Math.floor(Math.random()*0x800))+
+		int2str(Math.floor(Math.random()*0x80000000));
+}
 function notify(title,options) {
 	function show() {
 		var n=new Notification(title+' - '+_('extName'),{
@@ -603,12 +617,83 @@ function exportZip(z,src,callback){
 	var d={scripts:[],settings:settings},values=[];
 	getScripts();
 }
-var sxhr={};
-function registerXHR(id,src,callback){
-	sxhr[id]=1;
-	// XHR should be sent immediately after registration
-	setTimeout(function(){delete sxhr[id];},1000);
-	callback();
+
+// Requests
+var requests={},request_id_map={},special_headers=['user-agent'];
+function getRequestId(data,src,callback) {
+  var id=getUniqId();
+	// XHR, finalUrl, requestId in browser
+  requests[id]=[new XMLHttpRequest(),'',''];
+	callback(id);
+}
+function httpRequest(details,src,callback) {
+  function reqCallback(evt) {
+		function finish(){
+			chrome.tabs.sendMessage(src.tab.id,{
+				cmd: 'HttpRequested',
+				data: {
+					id: details.id,
+					type: evt.type,
+					resType: req.responseType,
+					data: data
+				}
+			});
+		}
+		var data={
+			finalUrl: reqo[1],
+			readyState: req.readyState,
+			responseHeaders: req.getAllResponseHeaders(),
+			status: req.status,
+			statusText: req.statusText
+		},r;
+		try {
+			data.responseText=req.responseText;
+		} catch(e) {}
+		if(req.response&&req.responseType=='blob') {
+			r=new FileReader();
+			r.onload=function(e){
+				data.response=r.result;
+				finish();
+			};
+			r.readAsDataURL(req.response);
+		} else {	// default `null` for blob and '' for text
+			data.response=req.response;
+			finish();
+		}
+		if(evt.type=='loadend') {
+			if(reqo[2]) delete request_id_map[reqo[2]];
+			delete requests[details.id];
+		}
+  }
+  var i,il,v,reqo=requests[details.id],req;
+	if(!reqo) return;req=reqo[0];
+  try {
+		// details.async=true;
+    req.open(details.method,details.url,true,details.user,details.password);
+		req.setRequestHeader('VM-Verify',details.id);
+    if(details.headers)
+			for(i in details.headers) {
+				v=details.headers[i];
+				if(special_headers.indexOf(i.toLowerCase())>=0) {
+					addSpecialHeader();
+					req.setRequestHeader('VM-'+i,v);
+				} else req.setRequestHeader(i,v);
+			}
+		if(details.responseType) req.responseType='blob';
+    if(details.overrideMimeType) req.overrideMimeType(details.overrideMimeType);
+    ['abort','error','load','loadend','progress','readystatechange','timeout'].forEach(function(i) {
+      req['on'+i]=reqCallback;
+    });
+		reqo[1]=details.url;
+		req.send(details.data);
+  } catch(e) {
+		console.log(e);
+  }
+}
+function abortRequest(id) {
+  var req=requests[id];
+  if(req) req.abort();
+  delete requests[id];
 }
 
 chrome.runtime.onConnect.addListener(function(p){
@@ -654,11 +739,13 @@ initDb(function(){
 			GetScript: getScript,	// for user edit
 			GetMetas: getMetas,	// for popup menu
 			SetBadge: setBadge,
-			RegisterXHR: registerXHR,
 			AutoUpdate: autoUpdate,
 			Vacuum: vacuum,
 			Move: move,
 			ParseMeta: function(o,src,callback){callback(parseMeta(o));},
+			GetRequestId: getRequestId,
+			HttpRequest: httpRequest,
+			AbortRequest: abortRequest,
 		},f=maps[req.cmd];
 		if(f) f(req.data,src,callback);
 		return true;
@@ -683,7 +770,6 @@ chrome.webRequest.onBeforeRequest.addListener(function(o){
 	urls:['<all_urls>'],types:['main_frame']
 },['blocking']);
 // Modifications on headers
-var allowed_headers=['user-agent'];
 chrome.webRequest.onBeforeSendHeaders.addListener(function(details) {
 	var headers=details.requestHeaders,new_headers=[],vm_headers={},v,i;
 	headers.forEach(function(header){
@@ -693,13 +779,25 @@ chrome.webRequest.onBeforeSendHeaders.addListener(function(details) {
 			new_headers.push(header);
 	});
 	v=vm_headers['Verify'];
-	if(v&&sxhr[v]) {
+	if(v&&(i=requests[v])) {
+		delete vm_headers['Verify'];
+		request_id_map[details.requestId]=v;
+		i[2]=details.requestId;
 		for(i in vm_headers)
-			if(allowed_headers.indexOf(i.toLowerCase())>=0)
+			if(special_headers.indexOf(i.toLowerCase())>=0)
 				new_headers.push({name:i,value:vm_headers[i]});
-		delete sxhr[v];
 	}
 	return {requestHeaders: new_headers};
 },{
 	urls:['<all_urls>'],types: ['xmlhttprequest'],
 },["blocking", "requestHeaders"]);
+// Watch URL redirects
+chrome.webRequest.onBeforeRedirect.addListener(function(details) {
+	var v=request_id_map[details.requestId],reqo;
+	if(v) {
+		reqo=requests[v];
+		if(reqo) reqo[1]=details.redirectUrl;
+	}
+},{
+	urls:['<all_urls>'],types: ['xmlhttprequest'],
+});

+ 12 - 89
injected.js

@@ -24,19 +24,6 @@ function utf8decode (utftext) {
 	}
 	return string;
 }
-function getUniqId() {
-	function int2str(i) {
-		var k='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_+',
-				s='',m;
-		while(i>0) {
-			m=i%64;
-			s+=k[m];
-			i=Math.floor(i/64);
-		}
-		return s;
-	}
-	return int2str(Date.now())+int2str(Math.floor(Math.random()*2147483647));
-}
 
 // Messages
 chrome.runtime.onMessage.addListener(function(req,src) {
@@ -44,6 +31,7 @@ chrome.runtime.onMessage.addListener(function(req,src) {
 		Command:command,
 		GetPopup:getPopup,
 		GetBadge:getBadge,
+		HttpRequested:httpRequested,
 	},f=maps[req.cmd];
 	if(f) f(req.data,src);
 });
@@ -147,10 +135,6 @@ var comm={
 						}
 						d.data.response=t.data[0];
 					}
-					// finalUrl not supported
-					Object.defineProperty(d.data,'finalUrl',{
-						get:function(){console.log('[Violentmonkey]Warning: finalUrl not supported for GM_xmlhttpRequest yet!');}
-					});
 					c(d.data);
 				}
 				if(d.type=='loadend') delete comm.requests[t.id];
@@ -182,7 +166,9 @@ var comm={
 						abort:reqAbort,
 					},
 					data:[],
-				};
+				},a=document.createElement('a');
+				a.setAttribute('href',details.url);
+				details.url=a.href;
 				comm.qrequests.push(t);
 				comm.post({cmd:'GetRequestId'});
 				return t.req;
@@ -440,82 +426,19 @@ function command(o){
 }
 
 // Requests
-var requests={};
 function getRequestId() {
-  var id=getUniqId();
-  requests[id]=new XMLHttpRequest();
-	comm.post({cmd:'GotRequestId',data:id});
+	chrome.runtime.sendMessage({cmd:'GetRequestId'},function(id){
+		comm.post({cmd:'GotRequestId',data:id});
+	});
 }
 function httpRequest(details) {
-  function callback(evt) {
-		function finish(){
-			comm.post({
-				cmd: 'HttpRequested',
-				data: {
-					id: details.id,
-					type: evt.type,
-					resType: req.responseType,
-					data: data
-				}
-			});
-		}
-		var data={
-			readyState: req.readyState,
-			responseHeaders: req.getAllResponseHeaders(),
-			status: req.status,
-			statusText: req.statusText
-		},r;
-		try {
-			data.responseText=req.responseText;
-		} catch(e) {}
-		if(req.response&&req.responseType=='blob') {
-			r=new FileReader();
-			r.onload=function(e){
-				data.response=r.result;
-				finish();
-			};
-			r.readAsDataURL(req.response);
-		} else {	// default `null` for blob and '' for text
-			data.response=req.response;
-			finish();
-		}
-		if(evt.type=='loadend') delete requests[details.id];
-  }
-  var i,il,v,sid=null,req=requests[details.id];
-	function addSpecialHeader(){
-		if(sid) return;
-		sid=getUniqId();
-		req.setRequestHeader('VM-Verify',sid);
-	}
-  if(req) try {
-		// details.async=true;
-    req.open(details.method,details.url,true,details.user,details.password);
-    if(details.headers)
-			for(i in details.headers) {
-				il=i.toLowerCase();
-				v=details.headers[i];
-				if(il=='user-agent') {
-					addSpecialHeader();
-					req.setRequestHeader('VM-User-Agent',v);
-				} else req.setRequestHeader(i,v);
-			}
-		if(details.responseType) req.responseType='blob';
-    if(details.overrideMimeType) req.overrideMimeType(details.overrideMimeType);
-    ['abort','error','load','loadend','progress','readystatechange','timeout'].forEach(function(i) {
-      req['on'+i]=callback;
-    });
-		if(sid)
-			chrome.runtime.sendMessage({cmd:'RegisterXHR',data:sid},function(){req.send(details.data);});
-		else
-			req.send(details.data);
-  } catch(e) {
-		console.log(e);
-  }
+	chrome.runtime.sendMessage({cmd:'HttpRequest',data:details});
+}
+function httpRequested(data) {
+	comm.post({cmd:'HttpRequested',data:data});
 }
 function abortRequest(id) {
-  var req=requests[id];
-  if(req) req.abort();
-  delete requests[id];
+	chrome.runtime.sendMessage({cmd:'AbortRequest',data:id});
 }
 
 // For injected scripts

+ 1 - 1
manifest.json

@@ -1,6 +1,6 @@
 {
 	"name": "Violent monkey",
-	"version" : "2.1.6.9",
+	"version" : "2.1.7",
 	"manifest_version" : 2,
 	"description" : "__MSG_extDescription__",
 	"developer": {"name" : "Gerald", "url" : "http://geraldl.net"},