0

I have a webpage that has custom events that I would like to listen to with a chrome extension. Every time an order comes in, the webpage gets the order and updates a little notification number with how many orders are pending. I am looking to create a chrome extension to listen to this event and in future be able to select the order and perform actions on it.

First of all, is this possible?

In the website source code that I found through using F12 on Chrome I found the orderHandler.js file

var OrdersHandler=new(function(){this.getOrder=function(item_id,success,fail){try{$.ajax({url:'/api/orders/'+item_id,method:"GET",headers:{"Authorization":"Bearer "+Cookies.getJSON("access_token").access_token},success:function(response,status,xhr){if(response.success){if(typeof(success)=="function"){success(response.order);}}
else{if(typeof(fail)=="function"){fail(status,response.message);}}},error:function(response,status,statusName,xhr){if(typeof(fail)=="function"){if(typeof(response.responseJSON)==="object"&&typeof(response.responseJSON.message)==="string"){fail(response.status,response.responseJSON.message);}
else{fail(response.status,response.status==0?"Network error":statusName);}}}});}
catch(e){console.log(e);onFailure(-1,"Script error");}};this.getOrdersList=function(listName,success,fail){try{$.ajax({url:'/api/orders-list/'+listName,method:"GET",headers:{"Authorization":"Bearer "+Cookies.getJSON("access_token").access_token},success:function(response,status,xhr){if(response.success){if(typeof(success)=="function"){success(response.order_items);}}
else{if(typeof(fail)=="function"){fail(status,response.message);}}},error:function(response,status,statusName,xhr){if(typeof(fail)=="function"){if(typeof(response.responseJSON)==="object"&&typeof(response.responseJSON.message)==="string"){fail(response.status,response.responseJSON.message);}
else{fail(response.status,response.status==0?"Network error":statusName);}}}});}
catch(e){console.log(e);onFailure(-1,"Script error");}};this.getOrderItem=function(item_id,success,fail){try{$.ajax({url:'/api/order_items/'+item_id,method:"GET",headers:{"Authorization":"Bearer "+Cookies.getJSON("access_token").access_token},success:function(response,status,xhr){if(response.success){if(typeof(success)=="function"){success(response.order_item);}}
else{if(typeof(fail)=="function"){fail(status,response.message);}}},error:function(response,status,statusName,xhr){if(typeof(fail)=="function"){if(typeof(response.responseJSON)==="object"&&typeof(response.responseJSON.message)==="string"){fail(response.status,response.responseJSON.message);}
else{fail(response.status,response.status==0?"Network error":statusName);}}}});}
catch(e){console.log(e);onFailure(-1,"Script error");}};this.takeOrderItem=function(item_id,success,fail){try{$.ajax({url:'/api/order_items/'+item_id+"/take",method:"POST",headers:{"Authorization":"Bearer "+Cookies.getJSON("access_token").access_token},success:function(response,status,xhr){if(response.success){if(typeof(success)=="function"){success(response.order_item);}}
else{if(typeof(fail)=="function"){fail(status,response.message);}}},error:function(response,status,statusName,xhr){if(typeof(fail)=="function"){if(typeof(response.responseJSON)==="object"&&typeof(response.responseJSON.message)==="string"){fail(response.status,response.responseJSON.message);}
else{fail(response.status,response.status==0?"Network error":statusName);}}}});}
catch(e){console.log(e);onFailure(-1,"Script error");}};this.reprocessOrderItem=function(item_id,success,fail){try{$.ajax({url:'/api/order_items/'+item_id+"/reprocess",method:"POST",headers:{"Authorization":"Bearer "+Cookies.getJSON("access_token").access_token},success:function(response,status,xhr){if(response.success){if(typeof(success)=="function"){success(response.order_item);}}
else{if(typeof(fail)=="function"){fail(status,response.message);}}},error:function(response,status,statusName,xhr){if(typeof(fail)=="function"){if(typeof(response.responseJSON)==="object"&&typeof(response.responseJSON.message)==="string"){fail(response.status,response.responseJSON.message);}
else{fail(response.status,response.status==0?"Network error":statusName);}}}});}
catch(e){console.log(e);onFailure(-1,"Script error");}};this.setSupplierOrderItem=function(item_id,supplier_id,success,fail){try{$.ajax({url:'/api/order_items/'+item_id+"/change_supplier",method:"POST",headers:{"Authorization":"Bearer "+Cookies.getJSON("access_token").access_token,"Content-Type":"application/json"},data:JSON.stringify({supplier_id:supplier_id}),success:function(response,status,xhr){if(response.success){if(typeof(success)=="function"){success(response.order_item);}}
else{if(typeof(fail)=="function"){fail(status,response.message);}}},error:function(response,status,statusName,xhr){if(typeof(fail)=="function"){if(typeof(response.responseJSON)==="object"&&typeof(response.responseJSON.message)==="string"){fail(response.status,response.responseJSON.message);}
else{fail(response.status,response.status==0?"Network error":statusName);}}}});}
catch(e){console.log(e);onFailure(-1,"Script error");}};this.releaseOrderItem=function(item_id,success,fail){try{$.ajax({url:'/api/order_items/'+item_id+"/release",method:"POST",headers:{"Authorization":"Bearer "+Cookies.getJSON("access_token").access_token},success:function(response,status,xhr){if(response.success){if(typeof(success)=="function"){success(response.order_item);}}
else{if(typeof(fail)=="function"){fail(status,response.message);}}},error:function(response,status,statusName,xhr){if(typeof(fail)=="function"){if(typeof(response.responseJSON)==="object"&&typeof(response.responseJSON.message)==="string"){fail(response.status,response.responseJSON.message);}
else{fail(response.status,response.status==0?"Network error":statusName);}}}});}
catch(e){console.log(e);onFailure(-1,"Script error");}};this.setOrderItemEarnPrice=function(item_id,price,success,fail){try{$.ajax({url:'/api/order_items/'+item_id,method:"PATCH",data:JSON.stringify({earn_price:price}),headers:{"Authorization":"Bearer "+Cookies.getJSON("access_token").access_token,"Content-type":"application/json"},success:function(response,status,xhr){if(response.success){if(typeof(success)=="function"){success(response.order_item);}}
else{if(typeof(fail)=="function"){fail(status,response.message);}}},error:function(response,status,statusName,xhr){if(typeof(fail)=="function"){if(typeof(response.responseJSON)==="object"&&typeof(response.responseJSON.message)==="string"){fail(response.status,response.responseJSON.message);}
else{fail(response.status,response.status==0?"Network error":statusName);}}}});}
catch(e){console.log(e);onFailure(-1,"Script error");}};this.confirmOrderItemDelivered=function(item_id,success,fail){try{$.ajax({url:"/api/order_items/"+item_id+"/confirm_delivered",method:"POST",headers:{"Authorization":"Bearer "+Cookies.getJSON("access_token").access_token},success:function(response,status,xhr){if(response.success){if(typeof(success)=="function"){success(response.order_item);}}
else{if(typeof(fail)=="function"){fail(status,response.message);}}},error:function(response,status,statusName,xhr){if(typeof(fail)=="function"){if(typeof(response.responseJSON)==="object"&&typeof(response.responseJSON.message)==="string"){fail(response.status,response.responseJSON.message);}
else{fail(response.status,response.status==0?"Network error":statusName);}}}});}
catch(e){console.log(e);onFailure(-1,"Script error");}};this.markOrderItemDelivered=function(item_id,delivery_proof,files,success,fail){try{$.ajax({url:"/api/order_items/"+item_id+"/mark_delivered",method:"POST",data:JSON.stringify({delivery_proof:delivery_proof,files:files}),headers:{"Authorization":"Bearer "+Cookies.getJSON("access_token").access_token,"Content-type":"application/json"},success:function(response,status,xhr){if(response.success){if(typeof(success)=="function"){success(response.order_item);}}
else{if(typeof(fail)=="function"){fail(status,response.message);}}},error:function(response,status,statusName,xhr){if(typeof(fail)=="function"){if(typeof(response.responseJSON)==="object"&&typeof(response.responseJSON.message)==="string"){fail(response.status,response.responseJSON.message);}
else{fail(response.status,response.status==0?"Network error":statusName);}}}});}
catch(e){console.log(e);onFailure(-1,"Script error");}};this.addChatMessage=function(item_id,message,success,fail){if(message.length<3){return;}
try{$.ajax({url:'/api/order_items/'+item_id+"/chats",method:"POST",data:JSON.stringify({message:message}),headers:{"Authorization":"Bearer "+Cookies.getJSON("access_token").access_token,"Content-type":"application/json"},success:function(response,status,xhr){if(response.success){if(typeof(success)=="function"){success(response);}}
else{if(typeof(fail)=="function"){fail(status,response.message);}}},error:function(response,status,statusName,xhr){if(typeof(fail)=="function"){if(typeof(response.responseJSON)==="object"&&typeof(response.responseJSON.message)==="string"){fail(response.status,response.responseJSON.message);}
else{fail(response.status,response.status==0?"Network error":statusName);}}}});}
catch(e){console.log(e);onFailure(-1,"Script error");}};})();

A lot of the Handler seems to be failure cases and what message to output depending on that. I was having a hard time deciphering what it is doing and how I can make a background.js to listen to the getOrder function.

Any help with these would be greatly appreciated! Ask for any clarification in the comments!

UPDATE

Via the helpful comments below. I can see that the window.OrdersHandler has functions available enter image description here

Are these functions usable and how would I connect this to a Listener? chrome.runtime.addListener()?

BWhelan
  • 378
  • 1
  • 5
  • 16
  • If the `OrdersHandler` is global, it looks like you might be able to simply overwrite `OrdersHandler.getOrder` with your own function. Copy-paste the code from the original `getOrder` into it, and add whatever other functionality you need – CertainPerformance Feb 19 '20 at 03:36
  • @CertainPerformance that would be fantastic if it were that easy. How would I find out if OrdersHandler is global? This website I plan to do this for is not my website, so I don't have anymore access to the source code other than Chrome F12 DevTools – BWhelan Feb 19 '20 at 03:38
  • Sure, just open the console and type in `window.OrdersHandler`, see it it gives you something. Also, just my personal preference, but it might be easier to write a [userscript](https://stackoverflow.com/questions/60292446/run-my-javascript-code-on-every-page-on-my-browser-similar-to-how-a-chrome-exte/60292470#60292470) than to write a full-fledged browser extension if all you want to do is insert some JS into the page – CertainPerformance Feb 19 '20 at 03:39
  • Would a userscript give the functionality of being able to monitor this event constantly and react when the event is triggered? Also, I tried what you said in the console. I will update the question right now will what it shows – BWhelan Feb 19 '20 at 03:52
  • Yes, you can do pretty much anything with a userscript that you could accomplish if you had full control over the original website – CertainPerformance Feb 19 '20 at 03:53
  • Do you want to intercept *all* errors, or only errors for `getOrder`? – CertainPerformance Feb 19 '20 at 03:54
  • I don't really care as much about the errors, I just want to get the Order if there is no errors to it – BWhelan Feb 19 '20 at 03:56

1 Answers1

1

Because OrdersHandler is global, and because it has the properties you're interested in directly assigned to the object, you can overwrite the properties you care about with your own logic. All of the properties look to be of the form:

this.getOrder = function (item_id, success, fail) {
    try {
        $.ajax({
            url: '/api/orders/' + item_id, method: "GET", headers: { "Authorization": "Bearer " + Cookies.getJSON("access_token").access_token }, success: function (response, status, xhr) {
                if (response.success) { if (typeof (success) == "function") { success(response.order); } }
                else { if (typeof (fail) == "function") { fail(status, response.message); } }
            }, error: function (response, status, statusName, xhr) {
                if (typeof (fail) == "function") {
                    if (typeof (response.responseJSON) === "object" && typeof (response.responseJSON.message) === "string") { fail(response.status, response.responseJSON.message); }
                    else { fail(response.status, response.status == 0 ? "Network error" : statusName); }
                }
            }
        });
    }
    catch (e) { console.log(e); onFailure(-1, "Script error"); }
};

Once the parent OrdersHandler object is defined, simply overwrite the property (or properties) that you're interested in. Copy and paste the original code, and then add whatever custom logic you want. For example, to monkeypatch getOrder so that it logs the response.order when it succeeds, you could do:

OrdersHandler.getOrder = function (item_id, success, fail) {
    try {
        $.ajax({
            url: '/api/orders/' + item_id, method: "GET", headers: { "Authorization": "Bearer " + Cookies.getJSON("access_token").access_token }, success: function (response, status, xhr) {
                if (response.success) { if (typeof (success) == "function") {
                  console.log(response.order); // <--------------------------
                  success(response.order);
                } }
                else { if (typeof (fail) == "function") { fail(status, response.message); } }
            }, error: function (response, status, statusName, xhr) {
                if (typeof (fail) == "function") {
                    if (typeof (response.responseJSON) === "object" && typeof (response.responseJSON.message) === "string") { fail(response.status, response.responseJSON.message); }
                    else { fail(response.status, response.status == 0 ? "Network error" : statusName); }
                }
            }
        });
    }
    catch (e) { console.log(e); onFailure(-1, "Script error"); }
};

You can paste that code into the browser console once the site has loaded. You could also write a userscript to run that code automatically whenever you load the page. (You could also write an extension, but an extension is overkill when you only want to inject some JS into a page, IMO)

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320