[转]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 ...
随机推荐
- html浏览器兼容性 JavaScript语法
1. 在FireFox中能够使用与HTML节点对象ID属性值同样的JS变量名称,可是IE中不行. 解决的方法:在命名上区分HTML节点对象ID属性值和JS变量 2. IE不支持JS ...
- 终于会用c#中的delegate(委托)和event(事件)了
一.开篇忏悔 对自己最拿手的编程语言C#,我想对你说声对不起,因为我到现在为止才明白c#中的delegate和event是怎么用的,惭愧那.好了,那今天就趁月黑风高的夜晚简单来谈谈delegate和e ...
- Android开发手册 (Android的手工教程MtAndroid开发手册)
放出版许可协议 1.0 或者更新版本号. 未经版权全部者明白授权,禁止发行本文档及其被实质上改动的版本号. 未经版权全部者事先授权.禁止将此作品及其衍生作品以标准(纸质)书籍形式发行. 假设有兴趣再 ...
- 在VirtualBox安装OS X 10.10
下面将指导介绍了如何引入自由和强大VirtualBox安装在虚拟机上OS X Yosemite 10.10 法律免责声明:本指南旨在说明如何在定期购买的苹果电脑上创建一个虚拟机执行真正的Mac OS ...
- Openstack & Hadoop结合项目Sahara
Openstack 项目Sahara,主要是用来搭建Hadoop集群,利用虚拟出来的计算资源,高速搭建Hadoop集群. Sahara项目与OPenstack其它项目的关系: 图片转自:http:// ...
- Linux下一个C基本的编程----写进Blog在那之前
展望2周的实习吧. 各种酸甜苦辣.由于公司只是广告.毛承保让我去.严重的歧视.想也想开,争夺.结果让它成为.还是把它写自己的学习经验,我有同样的希望和迷茫的同学.少走一点弯路.行.切入正题: 一.參考 ...
- ThinkPHP 3.2 开放 cache注缓存,过滤非法字符
打开缓存配置文件 /Application/Common/conf/cache.php源代码如下面: <?php return array( //'配置项'=>'配置值' 'LAYOUT_ ...
- C#特性和反射
C#特性和反射 .NET编译器的任务之一就是为所有定义和引用的类型生成元数据描述.除了程序集中标准的元数据外,.NET平台还支持特定(attribute)把更多的元数据嵌入到程序集中. .NET特性扩 ...
- JAVA Static方法与单例模式的理解
近期用sonar測评代码质量的时候,发现一个问题,project中一些util类,曾经写的static方法都提示最好用单例的方式进行改正. 为此,我细致想了想,发现还是非常有道理的.这里谈谈我个人对s ...
- 九度oj题目&吉大考研11年机试题全解
九度oj题目(吉大考研11年机试题全解) 吉大考研机试2011年题目: 题目一(jobdu1105:字符串的反码). http://ac.jobdu.com/problem.php?pid=11 ...