[chromium-dev] Re: [chromium-extensions] Inter-extension communication API proposal
On Tue, Jul 28, 2009 at 6:02 PM, Matt Perry mpcompl...@chromium.org wrote: Two suggestions (one I accidentally sent only to James): chrome.extension.Port: // ID of the extension at the other side of this port. String senderID; Port currently has a 'tab' property if the sender was a tab. Maybe we should group these: chrome.extension.Port: Object sender: Object tab; // if the sender was a tab String id; // ID of the sending extension. chrome.extension: // Open a channel to another extension with the provided ID. // If no extension with the provided ID exists, nothing happens. // Otherwise the chrome.extension.onConnectExternal event is fired // to all components of the extension with the provided ID each time // the method is called. // The channel can optionally be named. This name will be sent along // with the onConnectExternal event Port connectExternal(string ID, [string channelName]) It makes more sense to me to have the API mirror the regular connect event: chrome.extension.connect(); // connects to my own extension other = new chrome.Extension('abcef...'); other.connect(); // connects to extension abcdef... The reason I shied away from this is that the behavior of the statement new chrome.Extension('abdef...').connect() is very different depending on if 'abcdef...' is the ID of the extension containing that code or a different one. It's also not clear from the documentation what an extension should expect to be able to do with the result of new chrome.Extension('abcdef...'). According to http://dev.chromium.org/developers/design-documents/extensions/content-scripts the available APIs in addition to connect() are the onConnect event, which another extension should _not_ have access to, and getURL(path), which seems like it would just return chrome-extension://abcdef.../path. Based on that I don't see much value in exposing the new chrome.Extension('abcdef...') syntax for inter-extension interaction. - James --~--~-~--~~~---~--~~ Chromium Developers mailing list: chromium-dev@googlegroups.com View archives, change email options, or unsubscribe: http://groups.google.com/group/chromium-dev -~--~~~~--~~--~--~---
[chromium-dev] Re: [chromium-extensions] Inter-extension communication API proposal
On Thu, Jul 30, 2009 at 10:44 AM, James Robinson jam...@google.com wrote: On Tue, Jul 28, 2009 at 6:02 PM, Matt Perry mpcompl...@chromium.orgwrote: Two suggestions (one I accidentally sent only to James): chrome.extension.Port: // ID of the extension at the other side of this port. String senderID; Port currently has a 'tab' property if the sender was a tab. Maybe we should group these: chrome.extension.Port: Object sender: Object tab; // if the sender was a tab String id; // ID of the sending extension. chrome.extension: // Open a channel to another extension with the provided ID. // If no extension with the provided ID exists, nothing happens. // Otherwise the chrome.extension.onConnectExternal event is fired // to all components of the extension with the provided ID each time // the method is called. // The channel can optionally be named. This name will be sent along // with the onConnectExternal event Port connectExternal(string ID, [string channelName]) It makes more sense to me to have the API mirror the regular connect event: chrome.extension.connect(); // connects to my own extension other = new chrome.Extension('abcef...'); other.connect(); // connects to extension abcdef... The reason I shied away from this is that the behavior of the statement new chrome.Extension('abdef...').connect() is very different depending on if 'abcdef...' is the ID of the extension containing that code or a different one. How is it different? Sounds like a bug to me. It's also not clear from the documentation what an extension should expect to be able to do with the result of new chrome.Extension('abcdef...'). According to http://dev.chromium.org/developers/design-documents/extensions/content-scripts the available APIs in addition to connect() are the onConnect event, which another extension should _not_ have access to, and getURL(path), which seems like it would just return chrome-extension://abcdef.../path. Based on that I don't see much value in exposing the new chrome.Extension('abcdef...') syntax for inter-extension interaction. The value is consistency. extensionObject.connect() is how you open a port to that extension. It should be the same regardless of who you're talking to. --~--~-~--~~~---~--~~ Chromium Developers mailing list: chromium-dev@googlegroups.com View archives, change email options, or unsubscribe: http://groups.google.com/group/chromium-dev -~--~~~~--~~--~--~---
[chromium-dev] Re: [chromium-extensions] Inter-extension communication API proposal
[bcc chromium-dev] On Thu, Jul 30, 2009 at 2:01 PM, Matt Perry mpcompl...@chromium.org wrote: On Thu, Jul 30, 2009 at 10:44 AM, James Robinson jam...@google.comwrote: On Tue, Jul 28, 2009 at 6:02 PM, Matt Perry mpcompl...@chromium.orgwrote: Two suggestions (one I accidentally sent only to James): chrome.extension.Port: // ID of the extension at the other side of this port. String senderID; Port currently has a 'tab' property if the sender was a tab. Maybe we should group these: chrome.extension.Port: Object sender: Object tab; // if the sender was a tab String id; // ID of the sending extension. chrome.extension: // Open a channel to another extension with the provided ID. // If no extension with the provided ID exists, nothing happens. // Otherwise the chrome.extension.onConnectExternal event is fired // to all components of the extension with the provided ID each time // the method is called. // The channel can optionally be named. This name will be sent along // with the onConnectExternal event Port connectExternal(string ID, [string channelName]) It makes more sense to me to have the API mirror the regular connect event: chrome.extension.connect(); // connects to my own extension other = new chrome.Extension('abcef...'); other.connect(); // connects to extension abcdef... The reason I shied away from this is that the behavior of the statement new chrome.Extension('abdef...').connect() is very different depending on if 'abcdef...' is the ID of the extension containing that code or a different one. How is it different? Sounds like a bug to me. It's also not clear from the documentation what an extension should expect to be able to do with the result of new chrome.Extension('abcdef...'). According to http://dev.chromium.org/developers/design-documents/extensions/content-scripts the available APIs in addition to connect() are the onConnect event, which another extension should _not_ have access to, and getURL(path), which seems like it would just return chrome-extension://abcdef.../path. Based on that I don't see much value in exposing the new chrome.Extension('abcdef...') syntax for inter-extension interaction. The value is consistency. extensionObject.connect() is how you open a port to that extension. It should be the same regardless of who you're talking to. In extension A with id 'a', the code: new chrome.Extension('a').connect() would fire an onConnect event at components of extension A. With the proposal, doing that same line of code in extension B with id 'b' an onConnectExternal event would be fired at components of extension A. The most consistent thing to do would be to use connect() and onConnect everywhere, but an extension needs to be aware of when a connection is coming from another component within the same extension and when it is coming from a different extension. Hence the connectExternal/onConnectExternal calls instead of reusing connect/onConnect. - James --~--~-~--~~~---~--~~ Chromium Developers mailing list: chromium-dev@googlegroups.com View archives, change email options, or unsubscribe: http://groups.google.com/group/chromium-dev -~--~~~~--~~--~--~---
[chromium-dev] Re: [chromium-extensions] Inter-extension communication API proposal
+chromium-dev I think this is great. I suggest creating a wiki page with a design for this so that we can refer to it whenever we implement, and a bug that refers to the wiki page. Up until now, we've been putting our designs here: http://dev.chromium.org/developers/design-documents/extensions (see proposed api), but that page isn't editable without a @chromium.org account. I've been thinking we should move that content to the wiki so that it is editable by all. So if you want, you could be the first. Besides that, a few minor comments: 1. I think we should add a permission for inter-extension communication once we have a permissions mechanism. That is, an extension should have to declare in the manifest which extensions it would like to contact. This is just a security precaution against the extension accidentally leaking privileges if it gets XSS'd or something. On Tue, Jul 28, 2009 at 10:58 AM, James Robinsonjam...@google.com wrote: I think that extensions should be able to communicate with each other using message passing. Currently, it's possible to do something like this: var ext = new chrome.Extension('abcdefgh...'); var port = ext.connect('channel from another world!'); port.postMessage({message: im in ur channel}); However, there are a few problems with this approach. First, it's probably a bug that it works. The more serious issue is that a onConnect event is fired at extension 'abcdefgh...' and there is no way for that extension to know that the port is not from a content script within the same extension but from another extension. An extension should be able to allow other extensions to open connections to it, be explicitly aware of where the connection is coming from, and then communicate with it using the existing chrome.extension.Port system. This would require two new APIs on the chrome.extension object, based on the ones presented in http://dev.chromium.org/developers/design-documents/extensions/content-scripts: // Open a channel to another extension with the provided ID. // If no extension with the provided ID exists, nothing happens. // Otherwise the chrome.extension.onConnectExternal event is fired // to all components of the extension with the provided ID each time // the method is called. // The channel can optionally be named. This name will be sent along with the // onConnectExternal event Port connectExternal(String ID, [String channelName]) 2. I think we can merge connect() and connectExternal() by adding an optional param to connect() that specifies the target extension. If omitted it defaults to the current extension. // Fired when another extension opens a channel to this extension via // chrome.extension.connectExternal(). // If a channelName was provided, it is accessible via port.name. Event onConnectExternal(Object port) In order for an extension to know what the other side of a connection is I'd also propose adding the following property to the chrome.extension.Port class: // ID of the extension at the other side of this port. String senderID; An extension could check this field in the onConnectExternal handler and compare it to a whitelist/blacklist to decide whether to attach onMessage handlers. An extension might also want to expose some UI to the user listing all connected extensions. The other issue to address is startup order. The order in which the scripts within different background pages is not defined, which is entirely reasonable, but it means that doing the obvious thing: script var port = chrome.extension.connectExternal('abcdef..'); /script would work unreliably depending on the exact order in which the background pages get loaded, the event handlers get registered, and the events are fired. To resolve this I think that all connectExternal () events be queued until each extension's background page has loaded, so that any handler registration code in top-level scripts has a chance to run. This seems reasonable. It might be possible to be even cleverer if we know who wants to connect to who by way of what they declare in their manifests. - a --~--~-~--~~~---~--~~ Chromium Developers mailing list: chromium-dev@googlegroups.com View archives, change email options, or unsubscribe: http://groups.google.com/group/chromium-dev -~--~~~~--~~--~--~---
[chromium-dev] Re: [chromium-extensions] Inter-extension communication API proposal
On Tue, Jul 28, 2009 at 11:30 AM, Drew Wilsonatwil...@chromium.org wrote: SGTM. Note that we're essentially duplicating (assumedly intentionally so) the window.postMessage() APIs which require specifying a target domain and whose connect event has a source and origin attribute specifying the window that sent the message. Yeah, intentionally so. It seemed OK in this instance to not try and couple ourselves directly to postMessage() since the shape of extensions and web pages are slightly different. In the future, if it gets easier to use IDL (I hear other teams on Chromium are working on this), we might adopt something closer to postMessage(). It's an excellent point about connectExternal and startup ordering - in fact, one of the problems with window.postMessage now is that there's no guarantee that your message will be delivered if the target window has not loaded yet. I brought this up in the original design discussions, that messages should be queued until the page either loads or fails. Web platform APIs should be deterministic! Blech. In extensions, we queue the messages :). - a --~--~-~--~~~---~--~~ Chromium Developers mailing list: chromium-dev@googlegroups.com View archives, change email options, or unsubscribe: http://groups.google.com/group/chromium-dev -~--~~~~--~~--~--~---
[chromium-dev] Re: [chromium-extensions] Inter-extension communication API proposal
Thanks for the feedback. I've created http://code.google.com/p/chromium/wiki/InterExtensionCommunication with the proposal and would appreciate if someone with an @chromium account could link to it from http://dev.chromium.org/developers/design-documents/extensions. I copied the proposal pretty much unchanged to get the page started but since it's a wiki anyone should be able to edit freely. Some comment replies inline: On Tue, Jul 28, 2009 at 2:30 PM, Drew Wilson atwil...@chromium.org wrote: SGTM. Note that we're essentially duplicating (assumedly intentionally so) the window.postMessage() APIs which require specifying a target domain and whose connect event has a source and origin attribute specifying the window that sent the message. It might be valuable to just explicitly adopt those interfaces wholesale, substituting extension IDs for domains. It's an excellent point about connectExternal and startup ordering - in fact, one of the problems with window.postMessage now is that there's no guarantee that your message will be delivered if the target window has not loaded yet. -atw On Tue, Jul 28, 2009 at 11:19 AM, Aaron Boodman a...@chromium.org wrote: +chromium-dev I think this is great. I suggest creating a wiki page with a design for this so that we can refer to it whenever we implement, and a bug that refers to the wiki page. Up until now, we've been putting our designs here: http://dev.chromium.org/developers/design-documents/extensions (see proposed api), but that page isn't editable without a @chromium.org account. I've been thinking we should move that content to the wiki so that it is editable by all. So if you want, you could be the first. Besides that, a few minor comments: 1. I think we should add a permission for inter-extension communication once we have a permissions mechanism. That is, an extension should have to declare in the manifest which extensions it would like to contact. This is just a security precaution against the extension accidentally leaking privileges if it gets XSS'd or something. I agree completely. On Tue, Jul 28, 2009 at 10:58 AM, James Robinsonjam...@google.com wrote: I think that extensions should be able to communicate with each other using message passing. Currently, it's possible to do something like this: var ext = new chrome.Extension('abcdefgh...'); var port = ext.connect('channel from another world!'); port.postMessage({message: im in ur channel}); However, there are a few problems with this approach. First, it's probably a bug that it works. The more serious issue is that a onConnect event is fired at extension 'abcdefgh...' and there is no way for that extension to know that the port is not from a content script within the same extension but from another extension. An extension should be able to allow other extensions to open connections to it, be explicitly aware of where the connection is coming from, and then communicate with it using the existing chrome.extension.Port system. This would require two new APIs on the chrome.extension object, based on the ones presented in http://dev.chromium.org/developers/design-documents/extensions/content-scripts : // Open a channel to another extension with the provided ID. // If no extension with the provided ID exists, nothing happens. // Otherwise the chrome.extension.onConnectExternal event is fired // to all components of the extension with the provided ID each time // the method is called. // The channel can optionally be named. This name will be sent along with the // onConnectExternal event Port connectExternal(String ID, [String channelName]) 2. I think we can merge connect() and connectExternal() by adding an optional param to connect() that specifies the target extension. If omitted it defaults to the current extension. This sounds like it should be possible, but since connect() takes an optional param 'name' of type string already and the ID will also be of type string it seems like this would be ambiguous. // Fired when another extension opens a channel to this extension via // chrome.extension.connectExternal(). // If a channelName was provided, it is accessible via port.name. Event onConnectExternal(Object port) In order for an extension to know what the other side of a connection is I'd also propose adding the following property to the chrome.extension.Port class: // ID of the extension at the other side of this port. String senderID; An extension could check this field in the onConnectExternal handler and compare it to a whitelist/blacklist to decide whether to attach onMessage handlers. An extension might also want to expose some UI to the user listing all connected extensions. The other issue to address is startup order. The order in which the scripts within different background pages is not defined, which is entirely reasonable, but
[chromium-dev] Re: [chromium-extensions] Inter-extension communication API proposal
On Tue, Jul 28, 2009 at 12:09 PM, James Robinsonjam...@google.com wrote: Thanks for the feedback. I've created http://code.google.com/p/chromium/wiki/InterExtensionCommunication with the proposal and would appreciate if someone with an @chromium account could link to it Done. I also created a bug: http://code.google.com/p/chromium/issues/detail?id=17910 This sounds like it should be possible, but since connect() takes an optional param 'name' of type string already and the ID will also be of type string it seems like this would be ambiguous. Yeah, I don't feel too strongly about it. I was bringing it up more as a possibility. I presume that whenever someone implements this they will pick the best of the several ways to phrase this. We'll always know what extension the onConnectExternal event will be fired at when the connectExternal() call is made, so at the very least we could promise that no onConnectExternal event will be fired at an extension until its background page, if there is one, has fully loaded. Queuing until all extensions' background pages load is a simpler way to guarantee the same thing. Using the manifests could be a way to have a clever implementation, but in general the best you can get out of manifests is a partial order of extensions and you might get cycles. True. I guess I am worried about blocking an extension from communicating with, eg, itself, until all other extensions have loaded their background pages. This doesn't seem fair. - a --~--~-~--~~~---~--~~ Chromium Developers mailing list: chromium-dev@googlegroups.com View archives, change email options, or unsubscribe: http://groups.google.com/group/chromium-dev -~--~~~~--~~--~--~---
[chromium-dev] Re: [chromium-extensions] Inter-extension communication API proposal
On Tue, Jul 28, 2009 at 12:20 PM, Aaron Boodmana...@chromium.org wrote: We'll always know what extension the onConnectExternal event will be fired at when the connectExternal() call is made, so at the very least we could promise that no onConnectExternal event will be fired at an extension until its background page, if there is one, has fully loaded. Queuing until all extensions' background pages load is a simpler way to guarantee the same thing. Using the manifests could be a way to have a clever implementation, but in general the best you can get out of manifests is a partial order of extensions and you might get cycles. True. I guess I am worried about blocking an extension from communicating with, eg, itself, until all other extensions have loaded their background pages. This doesn't seem fair. I like your other proposal best, of just queuing onConnect events fired at an extension until its background page has loaded. We should do this for extensions talking to themselves, too. - a --~--~-~--~~~---~--~~ Chromium Developers mailing list: chromium-dev@googlegroups.com View archives, change email options, or unsubscribe: http://groups.google.com/group/chromium-dev -~--~~~~--~~--~--~---
[chromium-dev] Re: [chromium-extensions] Inter-extension communication API proposal
Two suggestions (one I accidentally sent only to James): chrome.extension.Port: // ID of the extension at the other side of this port. String senderID; Port currently has a 'tab' property if the sender was a tab. Maybe we should group these: chrome.extension.Port: Object sender: Object tab; // if the sender was a tab String id; // ID of the sending extension. chrome.extension: // Open a channel to another extension with the provided ID. // If no extension with the provided ID exists, nothing happens. // Otherwise the chrome.extension.onConnectExternal event is fired // to all components of the extension with the provided ID each time // the method is called. // The channel can optionally be named. This name will be sent along // with the onConnectExternal event Port connectExternal(string ID, [string channelName]) It makes more sense to me to have the API mirror the regular connect event: chrome.extension.connect(); // connects to my own extension other = new chrome.Extension('abcef...'); other.connect(); // connects to extension abcdef... --~--~-~--~~~---~--~~ Chromium Developers mailing list: chromium-dev@googlegroups.com View archives, change email options, or unsubscribe: http://groups.google.com/group/chromium-dev -~--~~~~--~~--~--~---