-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error handling: Frontend and Extension #196
Comments
Progress report 1: Bobtimus API is mostly fine. Errors are handled cleanly at the moment. To get more fine-grained error reporting of individual things that fail to the client, we need to create more named errors (i.e. structs that implement |
Progress report 2: I had a look at the communication between in-page script, content-script, background-script and wasm-wallet. I think this can be made more resilient (which comes with better error reporting) if we employ different designs. Here are my findings (in order of which I would tackle them): 1. Use randomly generated events to mimic request-response between in-page script and content-scriptAt the moment, in-page script and content-script use a generic "message" event to pass things back and forth. This doesn't really scale very well because it means that all message handlers need to be updated as soon as new event type is added, plus the implementation of each function within We can solve this by using the JavaScript window.postMessage({
kind: '<function name>', // f.e. get-wallet-status
args: {}
responseEvent: '<random UUID>'
})
window.addEventListener("<random UUID>", listener); Given this unique mapping, we can avoid carrying along a Not only does this allow for a generic implementation and saving code, it is also more robust. The current implementation is susceptible to race-conditions if the same event is dispatched within a very short amount of time. 2. Make proper use of Promise-return types in background scriptAt the moment, the background script defines an Together with (1), we no longer need to set the message response kind which should greatly simplify this function and reduce the risk of errors being dropped or not reported. 3. Directly listen for messages in RustAt the moment, we use We could remove a lot of boilerplate (wasm_proxy and the entire background script) if we would register the message listener directly inside Rust instead of exposing functions, i.e. do something like: #[wasm_bindgen(start)]
pub fn setup() {
/// ... other setup code
/// This doesn't work exactly like this but that is not that important
browser.runtime().on_message().add_listener(|message, source| {
if message.type == 'get-wallet-status' {
// return wallet.get_status()
}
});
} It would be fairly trivial to write a proc-macro so the entire things looks like this: #[message_handler]
pub async fn get_wallet_status() -> WalletStatus {
// wallet.lock().await.get_status()
} The new flow would be: (3) Would also affect the background proxy but I don't think that is much of a big deal. The |
Thanks @thomaseizinger :) some thoughts/questions:
|
I am well aware of that which is why it is the last item in the last of what I would tackle. The benefits of doing this are not so much to make better use of Rust's type-system. The benefits would be cutting out the dumb pass-through layers of "wasm-proxy" and "background script" by directly registering the I would write a proc-macro that generates all this ugly boilerplate for you at compile-time. If this pans out as intended, all you need to write is: #[message_handler]
pub async fn get_wallet_status() -> WalletStatus {
// wallet.lock().await.get_status()
} To get the equivalent of: browser.runtime.onMessage.addListener(message => {
if message.type == 'get_wallet_status' {
// wallet.lock().await.get_status()
}
});
Isn't that what we want? If we also achieve (3), then all we need to do is:
That would give you good control over which exact errors you want to return from the wasm-wallet and they would pop out in a nice format in the in-page script without any further doing. |
The listener in `browser.runtime.onMessage.addListener` can handle promises. As such, we can directly _reject_ this promise if there is any error in invoking the various wallet functions. Such a rejected promise is then _caught_ inside the content script and forwarded as an event to the in-page script. The communication of the events between in-page script and content-script has been reworked. 1. The new implementation contains less duplicated code due to the use of a generic `invokeContentScript` function. 2. Every request is tagged with an ID which allows us to uniquely identify, which particular request failed. This should help with race conditions where the same event is fired multiple times. Related: comit-network#196.
The listener in `browser.runtime.onMessage.addListener` can handle promises. As such, we can directly _reject_ this promise if there is any error in invoking the various wallet functions. Such a rejected promise is then _caught_ inside the content script and forwarded as an event to the in-page script. The communication of the events between in-page script and content-script has been reworked. 1. The new implementation contains less duplicated code due to the use of a generic `invokeContentScript` function. 2. Every request is tagged with an ID which allows us to uniquely identify, which particular request failed. This should help with race conditions where the same event is fired multiple times. Related: comit-network#196.
The listener in `browser.runtime.onMessage.addListener` can handle promises. As such, we can directly _reject_ this promise if there is any error in invoking the various wallet functions. Such a rejected promise is then _caught_ inside the content script and forwarded as an event to the in-page script. The communication of the events between in-page script and content-script has been reworked. 1. The new implementation contains less duplicated code due to the use of a generic `invokeContentScript` function. 2. Every request is tagged with an ID which allows us to uniquely identify, which particular request failed. This should help with race conditions where the same event is fired multiple times. Related: comit-network#196.
I wrote up a summary of the current situation and problems I see with our approach of importing the wasm code: #228 I think a lot of our error handling problems stem from having all these pass-through layers. A simpler solution would very likely drastically improve this situation. I've also created a follow-up issue for how to proceed with bobtimus' API: #229 As for:
We can open up a separate issue for that as well, although I am not sure how important it is to separately track? It sounds very specific to the design of particular pages and forms, hence I am not sure if there is anything general to fix here. I think it would be best to record and fix those as independent issues. Closing this as a result. |
The listener in `browser.runtime.onMessage.addListener` can handle promises. As such, we can directly _reject_ this promise if there is any error in invoking the various wallet functions. Such a rejected promise is then _caught_ inside the content script and forwarded as an event to the in-page script. The communication of the events between in-page script and content-script has been reworked. 1. The new implementation contains less duplicated code due to the use of a generic `invokeContentScript` function. 2. Every request is tagged with an ID which allows us to uniquely identify, which particular request failed. This should help with race conditions where the same event is fired multiple times. Related: comit-network#196.
There is a need for improving the error handling in waves. Something like this is not really helpful :D
Incomplete list of error sources we need to deal with:
Note: if something goes wrong in the extension/wallet-lib the extension is basically dead.
The text was updated successfully, but these errors were encountered: