[转]How WebKit’s Event Model Works
原文:https://homes.cs.washington.edu/~burg/projects/timelapse/articles/webkit-event-implementation/
First, here are some definitions of major parts of WebKit:
- JavaScriptCore
- The JavaScript execution engine. It has no dependencies on other components.
- WebCore
- The page rendering/layout/event dispatching component. This is the vast majority of the codebase in size and complexity. It depends on JavaScriptCore (JSC). Several portions have different implementations for each platform, such as graphics, sound, network, user input handling, and run loop integration.
- WebKit
- A fairly small layer that makes WebCore easier to embed by exposing a higher-level interface. It depends on all of the above.
- WebKit2
- a more complicated split-process layer for embedding WebKit. It depends on all of the above.
What controls the course of computation?
WebKit2 uses a split process model, where the Web process runs WebCore to handle parsing, layout, rendering, and script running for one web view. The browser/chrome process handles non-rendering tasks such as network communications and niceties for the user, like bookmarks and printing. The browser process communicates with all of its Web processes via inter-process communication (IPC). Essentially, one can view these messages as a queue of events to be handled. I’ll refer to these events as IPC messages.
Occasionally during the course of rendering a page or running a script, WebKit needs to perform (possibly a lot of) computation some time in the future, using timer callbacks. Common uses are implementing JavaScript timers or animations, which must run frequently to fill in many animation frames. I’ll refer to these callbacks as timers.
Timers allow asynchronous computation, and fire in a FIFO fashion: several callbacks with the same timer interval (say, 100ms) will fire in the order that they were registered. But, if an interval for 1s is set immediately after an interval for 10s, the 1s timer should fire first. This is accomplished by using a priority queue to keep track of which timers to fire next. Intervals with less time remaining to completion have greater priority than longer intervals. Among intervals with the same time remaining, those registered earlier have greater priority.
Thus, computation in WebKit is initiated by processing messages on one of two queues:
- Callbacks from the timer priority queue.
- Messages from the Browser process across IPC..
How internal timers are implemented
Periodically, all timers that are due for firing are fired synchronously and evicted from the queue (or re-inserted, for reoccuring timers). This periodic action is performed by a platform-level timer, whose base class is WebCore::SharedTimer
. Each platform has its own event loop implementation, so each platform defines its own SharedTimer subclass that hooks into native event loops. The OSX subclass ofSharedTimer
(SharedTimerMac), for example, registers a Cocoa CFRunLoopTimer. This is later called periodically by the native event loop, which is invoked inside the WebKit2::RunLoop
implementation (RunLoopMac), which is called in the main() method of the Web process.
The shared timer callback is registered via the following code path: ThreadTimers::setSharedTimer(SharedTimer* timer) -> MainThreadSharedTimer->setFiredFunction(ThreadTimers::sharedTimerFired) -> SharedTimer->setFiredFunction(void) -> SharedTimerMac->setSharedTimerFiredFunction(void)
The SharedTimer
’s interval is continously adjusted to the interval of the next due timer. This reduces the number of callbacks by SharedTimer
to ThreadTimers::sharedTimerFired
in cases where few timers are active (or a long ways into the future). When it’s time for a timer to fire, the code path looks something like:
[NSApplication run] (native loop)
-> timerFired()
-> ThreadTimers::sharedTimerFired()
-> threadGlobalData().threadTimers().sharedTimerFiredInternal() [1]
-> WebCore::Timer<WebCore::YourClass>->fired()
Inside of [1] is where eligible timers are looped over and fired, and the SharedTimer
interval is possibly adjusted. The gist of routine is to fire events until none are ready to fire or we have exceeded a time limit.
The native run loop fires lots of other native timers and callbacks, as well. At every such point (notably in file IO, streams, networking, and graphics), WebKit includes an implementation for each port/platform, which may add or remove native events from the native RunLoop
.
How IPC messages are handled
The Browser process sends messages to each Web process to communicate information such as resource data, user input, window resize, etc. These messages are piped to the Web process, which creates a WorkItem for each message. These work items are queued on the native event loop, and performed in course. In the OSX port, the RunLoop::performWork
method is registered as aCFRunLoopSource—-in essence, it is registered as an additional source of events for the event loop. The body of performWork
copies the list of WorkItems present upon method entry, works through the copied items, and then returns. Note that new work items may arrive when copied ones are being processed; these will be handled in the next call to performWork
. Below is a typical sequence of calls leading from the native event loop through processing the IPC message to calling the respective WebCore handler.
[NSApplication run] (native event loop)
-> RunLoopMac::performWork(void*)
-> RunLoop::performWork()
-> CoreIPC::Connection::dispatchMessages()
-> CoreIPC::Connection::dispatchMessage()
-> WebKit::WebProcess::didReceiveMessage(connection, messageID,
arguments)
-> WebKit::WebPage::didReceiveWebPageMessage(connection, messageId,
arguments)
-> CoreIPC::handleMessage(arguments, WebPageMessageReceiver, targetFn)
-> targetFn(args...)
At the point of targetFn
, the message can be handled in several ways. The important thing to note is that once these handlers reach WebCore, they are handled synchronously.
Where do DOM events fit into this picture?
DOM events are the abstraction for event-driven programming in web applications and JavaScript. (TheMugshot paper has a good overview of the DOM event model.) However, DOM events have not yet come into the picture—-where do they originate from?
Most user input DOM events, such as clicks, scroll wheel, and keyboard, are created in response to corresponding IPC messages. In that case, the targetFn
above will mediate between the native or browser view of user input and the DOM event standards. This mediation also converts from raw screen coordinates to a DOM target, and excludes some events that should not be reflected into the DOM model as input (for example, clicking on a scrollbar). Here is a typical sequence of calls from IPC targetFn
to DOM dispatch as described in the above link:
WebKit::WebPage::mouseEvent(WebMouseEvent)
-> WebKit::handleMouseEvent(WebMouseEvent, Page)
-> WebCore::EventHandler::dispatchMouseEvent(eventType, targetNode,
clickCount, PlatformMouseEvent)
-> Node::dispatchMouseEvent(...)
-> EventDispatcher::dispatchEvent(Node, EventDispatchMediator)
-> MouseEventDispatchMediator::dispatchEvent(EventDispatcher)
-> EventDispatcher::dispatchEvent(Event) // performs event dispatch according to DOM standard.
It is possible for some DOM events to immediately fire other DOM events synchronously. For example, the default event handler for the space or enter keyboard event on the <input type=”submit”> element will typically fire a second DOM “submit” event on the containing <form> element. This can be seen in the body and callers of HTMLFormElement::submitImplicitly
. What are the important points?
The top-level event loop is usually defined by the respective WebKit port, such as Cocoa, QT, GTK, etc. Timers internal to WebCore are manually tracked and dispatched by a single native timer that participates in the native run (event) loop. IPC messages are also handled according to the native run loop, and sometimes lead to dispatching DOM user input events. DOM events can potentially be triggered directly by timers internal to WebCore. An example is that animation-related DOM events are triggered by a timer in the AnimationController::animationTimerFired
callback. In general though, user input is only triggered by IPC messages.
[转]How WebKit’s Event Model Works的更多相关文章
- This module embeds Lua, via LuaJIT 2.0/2.1, into Nginx and by leveraging Nginx's subrequests, allows the integration of the powerful Lua threads (Lua coroutines) into the Nginx event model.
openresty/lua-nginx-module: Embed the Power of Lua into NGINX HTTP servers https://github.com/openre ...
- 【转向Javascript系列】从setTimeout说事件循环模型
本文首发在alloyteam团队博客,链接地址http://www.alloyteam.com/2015/10/turning-to-javascript-series-from-settimeout ...
- JavaScript Interview Questions: Event Delegation and This
David Posin helps you land that next programming position by understanding important JavaScript fund ...
- 事件轮询 event loop
Understanding the node.js event loop The first basic thesis of node.js is that I/O is expensive: So ...
- java event
What is an Event? Change in the state of an object is known as event i.e. event describes the change ...
- Two kinds of item classification model architecture
Introduction: Introduction to Fusing-Probability model: Cause the input has two parts, one is item i ...
- JavaScript 事件对象event
什么是事件对象? 比如当用户单击某个元素的时候,我们给这个元素注册的事件就会触发,该事件的本质就是一个函数,而该函数的形参接收一个event对象. 注:事件通常与函数结合使用,函数不会在事件发生前被执 ...
- Flutter json 2 model with Built Value
Flutter json 2 model with Built Value Flutter中json转换model, 除了手动转之外, 就是利用第三方库做一些代码生成. 流行的库有: json_ser ...
- POI导入导出Excel(HSSF格式,User Model方式)
1.POI说明 Apache POI是Apache软件基金会的开源代码库, POI提供对Microsoft Office格式档案读和写的功能. POI支持的格式: HSSF - 提供读写Microso ...
随机推荐
- decimal system 2016
Problem Description As we know , we always use the decimal system in our common life, even using the ...
- Python开发环境的搭建(win7)
一个.安装和配置Python 事实上,在开发python最好ubuntu环境.简单和易于扩展每个package. 在谈到如何win7建筑物Python开发环境. 因为python十字-platform ...
- php_PHP与Mysql的连接
展示效果: 繁写: <?php echo "This is a test</br>"; echo "asdfasdfadsf"; ...
- 我们的空间是它圆——基于Poicare对宇宙的模型
一般 状态 在人类文明的开始,并探讨了空间和时间的混乱从来没有停止过.马跑得更快.鱼下潜深.鸟振翅高飞,但是,人类并没有很深的不满潜飞不高.为什么?其原因是,马跑得更快,但它不会不知道他们为什么会跑得 ...
- Myeclipse重装后的必要配置
一.JDK位置 每台机器同意多个jdk版本号存在,编译时选择须要使用的jdk就可以.MyEclipse->Properties->Java->Installed JRES选择jdk位 ...
- 通过EA导入数据库存在表结构并生成文档
通过EA导入数据库存在表结构并生成文档 慕课网,程序员升职加薪神器,点击免费学习 目录[-] 导入数据源,表结构 生成表结构的文档 Enterprise Architect 是超级强大项目管理功能 ...
- Asp.net MVC + EF + Spring.Net 项目实践(四)
这篇写一写如何使用Spring.net来解耦各个项目 1. 在接口层添加IStudentBLL文件,里面有GetStudent和GetAllStudents两个方法:然后在StudentBLL类里实现 ...
- IOS开发中绘制地图线路
地图应用经常会涉及到线路的绘制问题,ios下可以使用MKMapView进行地图开发,使用 MKOverlayView进行线路的绘制. 使用MKMapView添加MKMap.framework 和Cor ...
- css mainDiv和popbox居中
<style> .beCenter { width:460px; height:212px; background:#ccc; ...
- 把VBScript的函数迁移到C#.NET
原文:把VBScript的函数迁移到C#.NET VBScript 5.6 Functions C# code Abs System.Math.Abs Array New Object() { } A ...