Hi guys, that's a cross-post from dev.gaia - guys there pointed out that there may be more work for Gecko here than I anticipate. :)
=== Problem === FirefoxOS apps bootstrap code is quite messy and incoherent. Lack of API that would enable an App to control the System's behavior (like firstPaint) results in a lot of dirty hacks intended to provide decent app startup user experience. Preventing FOUC's, flickering, on-screen layout composition, both for apps and for the System itself (think - runtime localization) requires a lot of trickery and suboptimal heuristics and still depends on unreliable behavior like I/O or CPU speed. On top of that, lack of standardized way for the App to report it's bootstrapping progress makes it impossible to reliably measure such basic characteristics as startup performance or memory consumption. mozbrowserloadend/firstPaint/onload works for documents, but does not match how apps are loaded. We just don't know what does it mean that the App is loaded, so we're guessing. The one characteristic that we can use is firstPaint for performance and arbitrarily chosen 10 second delay for measuring memory consumption. That's all guesswork. This also incentivize developers to postpone more and more of bootstrapping post firstPaint which gives better values to firstPaint while it decreases the user experience due to post-firstPaint screen composition and unresponsive UI. === Proposed solution === I'd like to suggest implementation of a stage based bootstrapping process. The stages would be asynchronous, flexible and optional. Asynchronous means that firing the App code for given stage loading may launch asynchronous code (like data loading or worker operations) and the App will end the stage firing an event to notify the System when the stage is complete. Flexible means that code related to stages may be fired out of order and the behavior of the App bootstrapping may be adjusted to particular app needs (think: developer knowing that async data loading for stage4 does not block stage3 may initialize the loading for stage4 before stage3). Optional means that the App may skip each and every of the stages just by not defining function that the System is firing at the beginning of the stage. The result is a lightweight model that optionally enables the App authors to take over control over certain System operations and provides solid information to the System about the status of the App bootstrapping. The focus on the perceived user experience and universality of stage division makes the contract between the App author and the System work independently of the particular System UX and should not require any changes as the long term design of the System UI progresses. This form of feeding information from the App to the System may also potentially enable us to optimize B2G better for performance, memory usage and caching. === Flow === Stage 0 - this stage is initialized as soon as possible after the user initiated the App launching procedure. The goal is to instantly provide user feedback that his action has been registered by the System. System: At this point the System initializes JS bootstrap code if it's registered in the manifest.webapp. Stage 1 - this is an optional stage which allows the App to modify any initialization parameters at runtime. System: At this point the System initializes loading of the document from manifest.webbapp@launch_app Stage 2 - this stage is fired when the document's DOM is interactive. It enables all operations required to prepare the document to be displayed and may block firstPaint if needed. System: At this point the System draws the App screen and takes initial firstPaint performance measurement. Stage 3 - during this stage the App initializes it's UI (event handlers on buttons etc.) making the App's UI usable for the user. System: At this point the System knows that the App's UI is usable and may take another measurement. Stage 4 - this stage allows the App to load any data that should not block UI but is displayed on the main screen. (examples: first 10 text messages, wifi/sim card status in Settings, first bunch of emails) System: At this point the System knows that the screen is fully visible and usable and should not require reflows unless an event occurs. Another performance metric and optionally screenshot can be taken or reflow optimizations. Stage 5 - during this stage the App loads additional data that is not displayed on the screen, but is needed without user interactions. Remaining messages/emails, Browser's bookmarks/history or awesomebar data. System: At this point the System considers the App fully loaded, may take memory measurements. Here's a demo of how it may look like: http://labs.braniecki.net/gaia/bootstrap/ === Challenges === * Webby-ness The Stage Bootstrap proposal focused on UX of an App loading and as such is different from how HTML document loading works. The firstPaint blocking is introduced, layout is separated from UI and data. The question is how "webby" it can be and how can we make this model fit into the architecture of Web engines and standards. * Error recovery If the app decides to block firstPaint and fails to emit stage2complete event, we should be able to recognize it and react. Potential solutions may be: time limit and taking over firstPaint control in an event of uncaught Error. * Interpretability with The Web How can we make this architecture work in case the System is not Firefox OS but a Web Browser and in result does not recognize the stage bootstrapping system? One solution is to make the stage code fire on its own in case the System does not takeover. Can we make it work? === RFC === Let's start the discussion on the app bootstrapping and use this proposal as a starting point. - Do you think it may work? - Does it solve the problems described at the top? - Are there other approaches that may work better? Thanks, zb _______________________________________________ dev-b2g mailing list [email protected] https://lists.mozilla.org/listinfo/dev-b2g
