check message come from opener/parent + add message to not close window + only allow sendTrans

This commit is contained in:
wighawag 2016-05-11 22:20:26 +01:00
parent c72c4bf80e
commit 144696ef97
1 changed files with 124 additions and 55 deletions

View File

@ -69,7 +69,7 @@ The fist message the iframe/window send is a message containing the string "read
For ```eth_sendTransaction``` the "gas", "gasPrice" and "from" field need to be set in the rpc parameter so that the window can display the correct value. If not all of these are passed in, the window will return an error. For ```eth_sendTransaction``` the "gas", "gasPrice" and "from" field need to be set in the rpc parameter so that the window can display the correct value. If not all of these are passed in, the window will return an error.
Upon receiving such message, the iframe will perform the actual rpc call to the node but only if such a call is a read only call (not requiring an unlocked key). If it is not it will return a error. The window on the other will also accept ```eth_sendTransaction``` calls but will display a dialog so the user can accept or cancel the request. Upon receiving such message, the iframe will perform the actual rpc call to the node but only if such a call is a read only call (not requiring an unlocked key). If it is not it will return a error. The window on the other will only accept ```eth_sendTransaction``` calls but will display a dialog so the user can accept or cancel the request.
In all the cases, the iframe/window will send a message back to the dapp using the following object: In all the cases, the iframe/window will send a message back to the dapp using the following object:
``` ```
@ -252,6 +252,7 @@ That's it
var cancelButton = document.getElementById("cancel-button"); var cancelButton = document.getElementById("cancel-button");
var confirmButton = document.getElementById("confirm-button"); var confirmButton = document.getElementById("confirm-button");
var message = document.getElementById("message"); var message = document.getElementById("message");
var infoMessage = document.getElementById("infomessage");
var password = document.getElementById("password"); var password = document.getElementById("password");
var passwordField = document.getElementById("passwordField"); var passwordField = document.getElementById("passwordField");
var modalDialog = document.getElementById("modal-dialog"); var modalDialog = document.getElementById("modal-dialog");
@ -278,7 +279,11 @@ That's it
window.close(); window.close();
} }
function showWaiting(){ function showWaiting(text){
if(!text){
text = "Please wait..."
}
infoMessage.innerHTML = text;
pleaseWait.style.display = "block"; pleaseWait.style.display = "block";
form.style.display = "none"; form.style.display = "none";
} }
@ -286,6 +291,8 @@ That's it
function hideWaiting(){ function hideWaiting(){
pleaseWait.style.display = "none"; pleaseWait.style.display = "none";
form.style.display = "block"; form.style.display = "block";
window.onbeforeunload = null;
} }
function showMessage(title, message, callback, buttonText){ function showMessage(title, message, callback, buttonText){
@ -395,6 +402,11 @@ That's it
} }
var submitFunc = function(){ var submitFunc = function(){
window.onbeforeunload = function (event) {
if(!closedByCode){
return "do not close now as a transaction is progress, this cannot be canceled and we wait for an answer";
}
};
if(requireUnlock){ if(requireUnlock){
if(password.value == ""){ if(password.value == ""){
password.style.border = "2px solid red"; password.style.border = "2px solid red";
@ -402,7 +414,7 @@ That's it
} }
password.style.border = "none"; password.style.border = "none";
var params = [transactionInfo.from,password.value,3]; var params = [transactionInfo.from,password.value,3];
showWaiting(); showWaiting("Please wait...<br/>Do not close the window.");
sendAsync(data.url,{id:999992,method:"personal_unlockAccount",params:params},function(error,result){ sendAsync(data.url,{id:999992,method:"personal_unlockAccount",params:params},function(error,result){
if(error || result.error){ if(error || result.error){
showMessage("Error unlocking account", "Please retry.", hideWaiting); showMessage("Error unlocking account", "Please retry.", hideWaiting);
@ -411,7 +423,6 @@ That's it
sourceWindow.postMessage({id:data.id,result:result,error:error},sourceWindow.location.href); sourceWindow.postMessage({id:data.id,result:result,error:error},sourceWindow.location.href);
closeWindow(); closeWindow();
}); });
showWaiting();
} }
}); });
}else{ }else{
@ -425,14 +436,11 @@ That's it
}); });
showWaiting(); showWaiting();
} }
return false; return false;
} }
form.onsubmit = submitFunc; form.onsubmit = submitFunc;
confirmButton.onclick = submitFunc; confirmButton.onclick = submitFunc;
} }
function needToAndCanUnlockAccount(address,url,callback){ function needToAndCanUnlockAccount(address,url,callback){
@ -452,6 +460,9 @@ That's it
} }
function receiveMessage(event){ function receiveMessage(event){
if(event.source != source){
return;
}
if(firstUrl){ if(firstUrl){
if(firstUrl != event.origin){ if(firstUrl != event.origin){
return; return;
@ -473,56 +484,114 @@ That's it
} }
function processMessage(data, sourceWindow){ var allowedMethods = [
if(data.payload.method == "eth_sendTransaction" || data.payload.method == "eth_sign"){ "web3_clientVersion"
if(inIframe){ ,"web3_sha3"
sourceWindow.postMessage({id:data.id,result:null,error:{message:"Cannot make call that require an unlocked key (" + data.payload.method + ") via iframe"},type:"notAllowed"},sourceWindow.location.href); ,"net_version"
}else if(data.payload.method == "eth_sign"){ ,"net_peerCount"
sourceWindow.postMessage({id:data.id,result:null,error:{message:"cannot sign transaction (" + data.payload.method + ") via html",type:"notAllowed"}},sourceWindow.location.href); ,"net_listening"
}else{ ,"eth_protocolVersion"
var transactionInfo = null; ,"eth_syncing"
if(data.payload.params.length > 0){ ,"eth_coinbase"
if(data.payload.params[0]["gas"] && data.payload.params[0]["gasPrice"] && data.payload.params[0]["to"] && data.payload.params[0]["from"]){ ,"eth_mining"
transactionInfo = data.payload.params[0]; ,"eth_hashrate"
} ,"eth_gasPrice"
} ,"eth_accounts"
if(transactionInfo != null){ ,"eth_blockNumber"
needToAndCanUnlockAccount(transactionInfo.from,data.url,function(requireUnlock,canUnlock){ ,"eth_getBalance"
if(requireUnlock && canUnlock){ ,"eth_getStorageAt"
askAuthorization(transactionInfo,data,true, sourceWindow); ,"eth_getTransactionCount"
}else if(!requireUnlock){ ,"eth_getBlockTransactionCountByHash"
askAuthorization(transactionInfo,data,false,sourceWindow); ,"eth_getBlockTransactionCountByNumber"
}else if(requireUnlock && !canUnlock){ ,"eth_getUncleCountByBlockHash"
var messageHtml = document.createElement('span'); ,"eth_getUncleCountByBlockNumber"
addBlocky(messageHtml,transactionInfo.from); ,"eth_getCode"
messageHtml.appendChild(document.createElement('br')); ,"eth_sendRawTransaction"
var span = document.createElement('span'); ,"eth_call"
span.innerHTML = "You need to unlock your account first : <br/>" + transactionInfo.from; ,"eth_estimateGas"
messageHtml.appendChild(span); ,"eth_getBlockByHash"
,"eth_getBlockByNumber"
showMessage("Account Locked",messageHtml,function(){ ,"eth_getTransactionByHash"
processMessage(data,sourceWindow); ,"eth_getTransactionByBlockHashAndIndex"
}, "Done"); ,"eth_getTransactionByBlockNumberAndIndex"
} ,"eth_getTransactionReceipt"
,"eth_getUncleByBlockHashAndIndex"
}); ,"eth_getUncleByBlockNumberAndIndex"
}else{ ,"eth_getCompilers"
sourceWindow.postMessage({id:data.id,result:null,error:{message:"Need to specify from , to, gas and gasPrice"},type:"notValid"},sourceWindow.location.href); ,"eth_compileLLL"
closeWindow(); ,"eth_compileSolidity"
} ,"eth_compileSerpent"
} ,"eth_newFilter"
}else{ ,"eth_newBlockFilter"
sendAsync(data.url,data.payload,function(error,result){ ,"eth_newPendingTransactionFilter"
sourceWindow.postMessage({id:data.id,result:result,error:error},sourceWindow.location.href); ,"eth_uninstallFilter"
}); ,"eth_getFilterChanges"
} ,"eth_getFilterLogs"
,"eth_getLogs"
,"eth_getWork"
,"eth_submitWork"
,"eth_submitHashrate"
// ,"shh_post"
// ,"shh_version"
// ,"shh_newIdentity"
// ,"shh_hasIdentity"
// ,"shh_newGroup"
// ,"shh_addToGroup"
// ,"shh_newFilter"
// ,"shh_uninstallFilter"
// ,"shh_getFilterChanges"
// ,"shh_getMessages"
];
function isMethodAllowed(method){
return allowedMethods.indexOf(method) != -1;
} }
window.onbeforeunload = function (event) { function processMessage(data, sourceWindow){
if(!closedByCode){
source.postMessage({id:data.id,result:null,error:{message:"Not Authorized",type:"cancel"}},source.location.href); if(inIframe){
} if(isMethodAllowed(data.payload.method)){
}; sendAsync(data.url,data.payload,function(error,result){
sourceWindow.postMessage({id:data.id,result:result,error:error},sourceWindow.location.href);
});
}else{
sourceWindow.postMessage({id:data.id,result:null,error:{message:"method (" + data.payload.method + ") not allowed in iframe"},type:"notAllowed"},sourceWindow.location.href);
}
}else if(data.payload.method == "eth_sendTransaction"){
var transactionInfo = null;
if(data.payload.params.length > 0){
if(data.payload.params[0]["gas"] && data.payload.params[0]["gasPrice"] && data.payload.params[0]["to"] && data.payload.params[0]["from"]){
transactionInfo = data.payload.params[0];
}
}
if(transactionInfo != null){
needToAndCanUnlockAccount(transactionInfo.from,data.url,function(requireUnlock,canUnlock){
if(requireUnlock && canUnlock){
askAuthorization(transactionInfo,data,true, sourceWindow);
}else if(!requireUnlock){
askAuthorization(transactionInfo,data,false,sourceWindow);
}else if(requireUnlock && !canUnlock){
var messageHtml = document.createElement('span');
addBlocky(messageHtml,transactionInfo.from);
messageHtml.appendChild(document.createElement('br'));
var span = document.createElement('span');
span.innerHTML = "You need to unlock your account first : <br/>" + transactionInfo.from;
messageHtml.appendChild(span);
showMessage("Account Locked",messageHtml,function(){
processMessage(data,sourceWindow);
}, "Done");
}
});
}else{
sourceWindow.postMessage({id:data.id,result:null,error:{message:"Need to specify from , to, gas and gasPrice"},type:"notValid"},sourceWindow.location.href);
closeWindow();
}
}else{
sourceWindow.postMessage({id:data.id,result:null,error:{message:"method (" + data.payload.method + ") not allowed in popup"},type:"notAllowed"},sourceWindow.location.href);
}
}
function checkMessageNotReceived(){ function checkMessageNotReceived(){
if(noMessageReceivedYet){ if(noMessageReceivedYet){