[转]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 ...
随机推荐
- 经典算法题每日演练——第八题 AC自动机
原文:经典算法题每日演练--第八题 AC自动机 上一篇我们说了单模式匹配算法KMP,现在我们有需求了,我要检查一篇文章中是否有某些敏感词,这其实就是多模式匹配的问题. 当然你也可以用KMP算法求出,那 ...
- ocp11g培训内部教材_051课堂笔记(047)_SQL
OCP 051课堂笔记 目录 OCP 051课堂笔记... 1 第一章.Oracle命令类别:... 4 第二章.SQL的基本函数... 4 2.1 单行函数与多行函数... 4 2.2 单行函数的几 ...
- IIS7伪静态化URL Rewrite模块
原文 IIS7伪静态化URL Rewrite模块 在Win7安装了IIS7.5之后,搭建一些网站或者博客,但是IIS7.5本身没有URL Rewrite功能,也就是无法实现网址的伪静态化. 从网上找了 ...
- Swift入门教程:基本语法(三)
打印输出 Swift提供了2个打印输出函数 println :输出内容后会自动换行 print :对比println,少了个自动换行的功能 示例 输出字符串 println("欢迎学习传智播 ...
- (c#2.0)serialPort串口通讯
原文:(c#2.0)serialPort串口通讯 using System; using System.Collections.Generic; using System.ComponentModel ...
- Java发送get及post请求工具方法
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import ...
- <转>如何利用socket进行HTTP访问
原文:<转>如何利用socket进行HTTP访问 如何利用socket进行HTTP访问 平常我们要访问某个URL一般都是通过浏览器进行:提交一个URL请求后,浏览器将请求发向目标服务器或者 ...
- SQL Server中存储过程比直接运行SQL语句慢的原因
原文:SQL Server中存储过程比直接运行SQL语句慢的原因 在很多的资料中都描述说SQLSERVER的存储过程较普通的SQL语句有以下优点: 1. 存储过程只在创造时进行编译即可,以 ...
- JAVA 代码生成。SimpleCaptcha
去官方网站下载Jar包: http://simplecaptcha.sourceforge.net/ Javadocs: http://simplecaptcha.sourceforge.net/ja ...
- PHP 6:PHP 基本数据类型
原文:PHP 6:PHP 基本数据类型 本章将介绍PHP基本类型.相信我们已经熟悉了C/C++,C#或者Java里的任意一种语言.本章会以C#为比较语言.OK,如果你想学PHP,你最先考虑的是什么呢? ...