Closed bgins closed 1 year ago
The message protocol has changed to send Webnative state on connect and disconnect messages. In addition, data messages have been have been broken into filesystem and session messages.
Messages are sent from Webnative to the extension as window post messages. When the extension initially connects, it configures Webnative with an extension ID which is used to tag all messages sent to the extension. The tag lets the extension filter window post messages to only receive messages intended for it.
Each message includes some information about the state of Webnative:
type State = {
app: {
namespace: AppInfo | string
capabilities?: Permissions
}
fileSystem: {
dataRootCID: string | null
}
user: {
username: string | null
accountDID: string | null
agentDID: string
}
odd: {
version: string
}
}
Updated on April 21st, 2023.
The extension calls a connect function that is added to the global object (e.g. window
) by Webnative. When the connect function is called, Webnative sends a connect message to the extension:
globalThis.postMessage({
id: extensionId,
type: "connect",
timestamp: 1678487975,
state
})
The extension calls a disconnect function when it does not need messages to be sent from Webnative:
globalThis.postMessage({
id: extensionId,
type: "disconnect",
timestamp: 1678487975,
state
})
Webnative sends session create and destroy messages to the extension. Each message contains a detail field that includes the username and indicates the message type:
globalThis.postMessage({
id: extensionId,
type: "session",
timestamp: 1678487975,
state,
detail: {
type: "create",
username
}
})
globalThis.postMessage({
id: extensionId,
type: "session",
timestamp: 1678487975,
state,
detail: {
type: "destroy",
username
}
})
Webnative sends filesystem local-change and publish messages to the extension. Each message contains a detail field that includes the root CID, path on local-change, and indicates the message type:
globalThis.postMessage({
id: extensionId,
type: "filesystem",
timestamp: 1678487975,
state,
detail: {
type: "local-change",
root: "<root-cid>",
path
}
})
globalThis.postMessage({
id: extensionId,
type: "filesystem",
timestamp: 1678487975,
state,
detail: {
type: "publish",
root: "<root-cid>"
}
})
Summary
Problem
The extension does not communicate with Webnative.
Impact
The extension does not fulfill its primary purpose of debugging Webnative without this feature.
Solution
Implement a communication layer to interact with Webnative.
Detail
Communication methods
The extension can communicate with Webnative by a couple of methods:
window.navigator
)Webnative can only communicate with the extension using window post messages. We can check that the post messages are from the page where the extension's content script was injected by checking the
event.source
when receiving a window post message._Side note: Chrome supports an
externally_connectable
API that allows a page to send messages directly using the extension runtime. Firefox does not support this feature yet so we can discard it as an option for now._Connect
We will start the interaction between the extension and Webnative when a developer opens the Webnative devtools panel. The extension will signal to Webnative that it is ready to connect.
We could call a function put onto the global scope by Webnative or send a window post message to Webnative. I think calling a function would be preferable because it is a direct communication between the extension and Webnative. A window post message could be received elsewhere.
Webnative should send a
connected
window post message to the extension to confirm the connection. We can't directly target the extension with a window post message, but we can tag messages so the extension can ignore any other window post noise.The
connected
message could look like:We could go further configure Webnative with a unique
id
sent by the extension when it connects. For exampleThe main benefit here would be to ignore spoofed messages sent by another window poster. Not actually sure if we have a privacy or security concern, so a unique
id
might be overkill.Disconnect
We should add a disconnect as well. The extension might disconnect when the developer is not viewing the Webnative devtools panel. Also, Webnative may want to signal to the extension that it has disconnected because something went wrong.
Disconnect could be implemented in roughly the same way as connect. Webnative adds a disconnect function to the global scope that the extension can call. When called, Webnative responds with a
disconnect
message like:Data
Data messages are sent from Webnative to the extension. See https://github.com/webnative-examples/webnative-devtools/issues/2 for a list of data we would like to send.
We will send data messages as window post messages, and we can use a similar format to the other messages with an added
data
field:The
data
that we send must be JSON serializable because the message will pass through extension messaging APIs.