-
Notifications
You must be signed in to change notification settings - Fork 334
Add basic extension add-on framework. #2155
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
Conversation
This can be tested with: https://github.com/mozilla-iot/example-extension |
82ef2d8
to
cf3e839
Compare
There are a lot of things we can do to create more extension points, but this at least provides a starting point which already opens up a lot of possiblities. Fixes WebThingsIO#2143 Fixes WebThingsIO#2144
cf3e839
to
e4c894c
Compare
Codecov Report
@@ Coverage Diff @@
## master #2155 +/- ##
==========================================
- Coverage 70.4% 70.23% -0.17%
==========================================
Files 132 133 +1
Lines 7544 7594 +50
Branches 1187 1195 +8
==========================================
+ Hits 5311 5334 +23
- Misses 1928 1950 +22
- Partials 305 310 +5
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mrstegeman This looks great!
The way I imagined that defining a new menu entry would work is that the add-on developer could provide the content for their custom screen as HTML, CSS and JavaScript. This PR achieves the CSS and JS part of that by referring to those resources in content_scripts in the manifest, but currently any HTML has to be inserted into the DOM using JavaScript, using a reference to a top level DOM element returned in a method of the Extension
class.
Looking to Web Extensions for a precedent I see that popups can be defined in the way I described, by referencing an HTML file as part of a browser_action or page_action. See this extension for an example of a popup in a browser_action. There's also the background scripts mechanism whereby you can specify a background page, which can then itself load scripts.
It's a bit tricky to draw direct analogies between browser extensions and gateway extensions and define what is a content script vs. a browser action vs. a page action, because the gateway doesn't have the concept of chrome vs. content exactly. But I do wonder whether in defining the API for adding a custom UI section with its own menu entry, we could allow developers to provide a static HTML file rather than build the DOM entirely in JavaScript? That HTML could then either be inserted into the DOM when the extension is loaded, or even embedded in an iframe (may be a bad idea...).
I'm thinking out loud a bit here, because I'm not sure exactly what the best API would be. What do you think? Perhaps you've already thought through some potential alternative approaches?
I think that comparing to WebExtensions is a bit tricky in this case. WebExtensions are essentially given a standalone In our case, a menu entry essentially just references a Also, I'm unsure what the background page is actually used for in a WebExtension. MDN's example just shows it loading scripts, not having content. One possible workaround would be:
|
@mrstegeman wrote:
That's a good point. You could just copy the content of the I had the same instinct to avoid using an iframe, but I can't think of any specific problems with that. Can you?
A better example is probably a sidebar_action. Here is an example browser extension which demonstrates a sidebar provided as an HTML document (it also demonstrates the use of the context menu API which is interesting). What if we took a similar approach to sidebars where a custom section is defined in the manifest including its icon, title and HTML content: manifest.json
HTML content for a custom section could be provided as an HTML file referenced in the manifest. The HTML file could then load its own CSS and JavaScript files, rather than using the my_section.html
One problem I can think of with using an iframe to embed this content is that no CSS or JavaScript from the wider gateway application would be loaded into the page by default. This might make it tricky to provide APIs via global variables in the style of Web Extension APIs. The extension would have to include a script from the gateway itself. |
Yes, exactly. Manually moving scripts and links out of the
The biggest problem is the inability to access the global gateway APIs that we expose in the UI, and especially the JWT. Beyond that, I would say that as we add more extensions points, things may get really tricky if everything is isolated in an
That makes sense. But in this case, again, the extension gets an entire
I'm not necessarily opposed to the icon/title approach here (content discussed below). My biggest concern was localization, but I see that WebExtensions provide a way to localize strings in the manifest.
Yes, this is exactly the issue with using the iframe. I really like the idea of having all of the extension APIs pre-loaded into the browser, rather than having each extension load the same JS file. For example, if you have 10 extensions, you're going to load |
It's just my two cents, but being able to have a fully working html page, with css and js in it, sounds like it would make development a lot easier. |
@flatsiedatsie I don't disagree with you. How would you recommend we do that, though, without using an |
@benfrancis Check this out and see what you think: WebThingsIO/example-extension#1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@benfrancis Check this out and see what you think: WebThingsIO/example-extension#1
Thank you. I understood what you meant, but the code illustrates it well.
Personally I was thinking of an extension add-on as more of a self-contained mini web app (HTML, CSS & JS) that gets rendered inside a (conceptual) container with certain APIs exposed to it via globals, rather than extending a built-in class from the gateway application and explicitly extending a section of the gateway application's DOM itself from JavaScript. That seemed like a cleaner separation.
But maybe I'm just taking the analogy with Firefox add-ons too literally. The reality is that we're extending an existing web app, not a browser.
So if you think this is a better approach, then it's not a hill I'm going to die on :)
Yeah, I think it's fundamentally different. If you look at Voice Fill, which does draw content directly to web pages (Google, Yahoo, etc.), it does so through JS, not by loading HTML. I think something like that is a better analogy here. |
I wasn't advocating for an iframe option (although one advantage of that might be security? A rogue add-on could make less of a mess?). Mostly just that loading in a html file would indeed be nice. Perhaps bake that in, as was suggested. I could imagine, for example, a separate development support tool that merges the html, css and js for quick previews. I was also thinking that it could be nice to have the example add-on come with some example html built in. A basic container, some buttons. It would help developers get started quickly, and it would help new add-ons conform to the Gateway's style. |
The example-extension has some HTML and fetches it asynchronously. See here. |
There are a lot of things we can do to create more extension points,
but this at least provides a starting point which already opens up a
lot of possiblities.
Fixes #2143
Fixes #2144