浏览器探究——webkit部分——HTMLinput标签
测试页面
<html>
<body>
First name: <input type="text"name="fname" />
Last name: <input type="text"name="lname" />
</body>
</html>
这里不看DOM的构建以及layout和Rander的处理等,这里只关注下input标签的一些基本的处理情况。
HTMLInputElement
HTML的Input标签的类结构。
class HTMLInputElement : publicHTMLTextFormControlElement, public InputElement
看下集成关系
Node
ContainerNode
Element
StyledElement
HTMLElement FormAssociateElement
HTMLFormControlElement
HTMLFormControlElementWithState InputElement
HTMLInputElement
HTMLInputElement的创建
#0WebCore::HTMLInputElement::create
#1 inputConstructor
#2WebCore::HTMLElementFactory::createHTMLElement
#3WebCore::HTMLConstructionSite::createHTMLElement
#4WebCore::HTMLConstructionSite::insertSelfClosingHTMLElement
#5WebCore::HTMLTreeBuilder::processStartTagForInBody
#6WebCore::HTMLTreeBuilder::processStartTag
#7WebCore::HTMLTreeBuilder::processToken
#8WebCore::HTMLTreeBuilder::constructTreeFromAtomicToken
#9WebCore::HTMLTreeBuilder::constructTreeFromToken
#10WebCore::HTMLDocumentParser::pumpTokenizer
#11WebCore::HTMLDocumentParser::pumpTokenizerIfPossible
#12WebCore::HTMLDocumentParser::append
#13WebCore::DecodedDataDocumentParser::appendBytes
#14WebCore::DocumentWriter::addData
#15WebCore::DocumentWriter::endIfNotLoadingMainResource
#16WebCore::DocumentWriter::end
#17WebCore::DocumentLoader::finishedLoading
#18WebCore::FrameLoader::finishedLoading
#19WebCore::MainResourceLoader::didFinishLoading
#20WebCore::ResourceLoader::didFinishLoading
#21 android::WebUrlLoaderClient::didFinishLoading
这一长串基本上是构建DOM的一个主体流程,当前对构建DOM的过程先不看,先看下结果是什么。在HTMLElementFactory::createHTMLElement中会根据参数QualifiedNameqname创建一个相关类型的Element,当前qname的toString()方法可以返回它的值,这里是”input”。根据qName的值,HTMLElementFactory::createHTMLElement会从一个FunctionMap中找到合适的创建方法,来创建相应的HTMLElement,即这个是个工厂类,从中找出需要创建那种产品的HTMLElement类的构造器,然后通过构造器创建出具体的产品HTMLElement。
这样经过了HTMLElementFactory::createHTMLElement后就找到了构造器inputConstructor,通过该构造器又可以调用到HTMLInputElement::create方法,该方法就是自己创建一个自己的实例的方法了。
那么经过HTMLInputElement::create的操作,一个HTMLInputElement实例被new出来了。
属性的设置
在构建完HTMLInputElement后,HTMLConstructionSite::createHTMLElement会向这个Element中设置相应的属性,通过Element::setAttributeMap函数。当期间有属性添加,修改,删除时会调用Element::attributeChanged来通知并更新该属性情况。
RenderTextControlSingleLine的创建
在完成了上述的Element的创建之后,就是与该Element对应的Renderer的创建了
#0WebCore::TextFieldInputType::createRenderer
#1WebCore::HTMLInputElement::createRenderer
#2WebCore::Node::createRendererAndStyle
#3WebCore::Node::createRendererIfNeeded
#4 WebCore::Element::attach
#5WebCore::HTMLFormControlElement::attach
#6WebCore::HTMLInputElement::attach
#7WebCore::HTMLConstructionSite::attach
#8WebCore::HTMLConstructionSite::attachToCurrent
#9WebCore::HTMLConstructionSite::insertSelfClosingHTMLElement
#10WebCore::HTMLTreeBuilder::processStartTagForInBody
#11WebCore::HTMLTreeBuilder::processStartTag
#12WebCore::HTMLTreeBuilder::processToken
在HTMLConstructionSite::insertSelfClosingHTMLElement创建完Element之后,紧跟着就会执行HTMLConstructionSite::attachToCurrent的操作来创建与该Element对应的Renderer。
对于Element的祖先Node,提供了一个虚函数attach
// Attaches this node to the rendering tree. This calculates thestyle to be applied to the node and creates an
// appropriate RenderObject which will be inserted into the tree (exceptwhen the style has display: none). This
// makes the node visible in the FrameView.
virtual voidattach();
该函数是个重要的函数,Element的继承子类中,大多实现了该attach函数,用来创建与自己类型对应的Renderer。
另外Node还有个虚函数virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
该函数用于创建与该Node对应的RenderObject的。
这里HTMLInputElement也实现了自己的attach方法和createRenderer方法,最终创建了与之对应的RenderTextControlSingleLine。
看下RenderTextControlSingleLine的继承体系:
CachedResourceClient
RenderObject
RenderBoxModelObject
RenderBox
RenderBlock
RenderTextControl PopupMenuClient
RenderTextControlSingleLine
其实这套继承体系主要就是按照css规范做的。
在RenderObject类中有成员Node* m_node;在创建相应的RenderObject子类时,会设置该m_node为RenderObject对应的Node。
在Node类中有成员RenderObject* m_renderer;在Node::createRendererAndStyle中,创建完RenderObject后,就会通过Node::setRenderer把新的Renderer设置给m_renderer
这样Node和RenderObject就相互关联上了。
设置RenderStyle
这里有一个类RenderStyle,在Node:: createRenderer方法中,会传入这个参数。这个类包含了一些Style用于构造对应的RenderObject时用,但是RenderTextControlSingleLine的构造时没用到。
在RenderObject中还有函数setStyle,可以用来设置RenderStyle的。另外有个setAnimatableStyle函数不知道跟setStyle有什么区别,但是setAnimatableStyle最终还是调用setStyle来设置RenderStyle。
在RenderObject构造完并设置给Node后,就会调用这个RenderObject::setAnimatableStyle来为RenderObject设置RenderStyle。
RenderTextControlSingleLine::layout和RenderTextControlSingleLine::paint
对于RenderObject来说RenderObject::layout和RenderObject:: paint是最重要的两个函数了。这里只看下调用栈
#0WebCore::RenderTextControlSingleLine::layout
#1WebCore::RenderObject::layoutIfNeeded
#2WebCore::RenderBlock::layoutInlineChildren
#3WebCore::RenderBlock::layoutBlock
#4 WebCore::RenderBlock::layout
#5WebCore::RenderBlock::layoutBlockChild
#6WebCore::RenderBlock::layoutBlockChildren
#7WebCore::RenderBlock::layoutBlock
#8WebCore::RenderBlock::layout
#9WebCore::RenderBlock::layoutBlockChild
#10WebCore::RenderBlock::layoutBlockChildren
#11WebCore::RenderBlock::layoutBlock
#12WebCore::RenderBlock::layout
#13WebCore::RenderView::layout
#14WebCore::FrameView::layout
#15WebCore::Document::implicitClose
#16WebCore::FrameLoader::checkCallImplicitClose
#17WebCore::FrameLoader::checkCompleted
#18WebCore::FrameLoader::finishedParsing
#19WebCore::Document::finishedParsing
#20WebCore::HTMLTreeBuilder::finished
#21WebCore::HTMLDocumentParser::end
#22WebCore::HTMLDocumentParser::attemptToRunDeferredScriptsAndEnd
#23 WebCore::HTMLDocumentParser::prepareToStopParsing
#24WebCore::HTMLDocumentParser::attemptToEnd
#25WebCore::HTMLDocumentParser::finish
#26WebCore::Document::finishParsing
#27WebCore::DocumentWriter::endIfNotLoadingMainResource
#28WebCore::DocumentWriter::end
#29 WebCore::DocumentLoader::finishedLoading
#30WebCore::FrameLoader::finishedLoading
#31WebCore::MainResourceLoader::didFinishLoading
#32WebCore::ResourceLoader::didFinishLoading
#33android::WebUrlLoaderClient::didFinishLoading
layout的细节不去看了,很麻烦,以后专门去研究下。这里有个印象就好。
#0WebCore::RenderTextControlSingleLine::paint
#1WebCore::InlineBox::paint
#2WebCore::InlineFlowBox::paint
#3WebCore::RootInlineBox::paint
#4WebCore::RenderLineBoxList::paint
#5WebCore::RenderBlock::paintContents
#6WebCore::RenderBlock::paintObject
#7WebCore::RenderBlock::paint
#8WebCore::RenderBlock::paintChildren
#9WebCore::RenderBlock::paintContents
#10WebCore::RenderBlock::paintObject
#11WebCore::RenderBlock::paint
#12WebCore::RenderLayer::paintLayer
#13WebCore::RenderLayer::paintList
#14WebCore::RenderLayer::paintLayer
#15WebCore::RenderLayer::paint
#16WebCore::FrameView::paintContents
#17android::WebFrameView::draw
#18android::WebViewCore::rebuildPicture
#19android::WebViewCore::rebuildPictureSet
#20android::WebViewCore::recordPictureSet
#21android::WebViewCore::recordContent
#22 RecordContent
#23 dvmPlatformInvoke()
paint的细节不去看了,很麻烦,以后专门去研究下。这里有个印象就好。
点击事件
当点击输入框时,java层会受到该事件,该事件最终会在WebViewCore.java的handleMessage中通过nativeMoveMouseIfLatest这个jni函数,把事件传递到c层。
C层的WebViewCore会通过Frame找到EventHandler。
EventHandler
EventHandler是c层事件的总入口,提供了对各种时间的处理接口,当前是点击事件,则实际上先收到的是moveMouse事件,因为手机上没有鼠标,而点击时,会先认为讲鼠标移动到该位置了,所以调用了moveMouse事件。对应的EventHandle的处理就是handleMouseMoveEvent函数。
EventHandle::handleMouseMoveEvent
该函数做了一定的处理后,执行了EventHandler::dispatchMouseEvent,即将这个事件转发出去。handleMouseMoveEvent最主要的处理是,找出哪个Node会被接收并处理事件。即当前找出鼠标移动到哪个Node上了。然后在EventHandler::dispatchMouseEvent中即可把事件转发给该Node去处理了,这里调用的是Node::dispatchMouseEvent。可见EventHandler就是事件的汇总处,接收到事件后,判断要让哪个Node来处理,然后就会调用该Node的相应的事件处理接口。
Node::dispatchMouseEvent
到了这里,事件已经通过EventHandler到了某个具体的Node上了。但是Node直接把处理交给了EventDispatcher::dispatchEvent这个静态函数,让它负责做转发的处理。
EventDispatcher
这个类有一些静态函数,用于做事件的分发,其实这个就是对事件做一下包装和转换,做一些额外的处理,最终还是会用某种策略把事件传递给具体需要处理的Node上。调用具体Node的处理函数。也就是它作为了一个中转层,在它处理之前已经知道是什么事件,并作用在什么Node上了。但是它做了一些额外的处理后,在根据一个策略来调用Node的处理函数。
最终该事件到达HTMLInputElement::defaultEventHandler(Event* evt)中。
看下调用栈:
#0 WebCore::HTMLInputElement::defaultEventHandler
#1 WebCore::EventDispatcher::dispatchEvent
#2WebCore::MouseEventDispatchMediator::dispatchEvent
#3WebCore::EventDispatcher::dispatchEvent
#4WebCore::Node::dispatchMouseEvent
#5 WebCore::EventHandler::dispatchMouseEvent
#6 WebCore::EventHandler::handleMouseMoveEvent
#7 android::WebViewCore::moveMouse
#8 android::WebViewCore::moveMouseIfLatest
#9 MoveMouseIfLatest
输入字符
当输入字符时,同样会触发HTMLInputElement::defaultEventHandler,此时栈情况为:
#0WebCore::InputElementData::setValue
#1 WebCore::InputElement::setValueFromRenderer
#2WebCore::HTMLInputElement::setValueFromRenderer
#3 WebCore::RenderTextControlSingleLine::subtreeHasChanged
#4WebCore::HTMLFormControlElementWithState::defaultEventHandler
#5WebCore::HTMLInputElement::defaultEventHandler
可见,在HTMLInputElement的defaultEventHandelr处理中的最后会调用基类的defaultEventHandelr。
这个基类HTMLFormControlElementWithState的处理中会做个如下的判断
if (event->type() ==eventNames().webkitEditableContentChangedEvent && renderer() &&renderer()->isTextControl())
即判断了event的类型和renderer的类型后,执行了RenderTextControlSingleLine::subtreeHasChanged的操作。
RenderTextControlSingleLine::subtreeHasChanged
这个函数中,会通过基类RenderTextControl获取到当前输入的text值,然后把这个值赋给与它对应的Node中,即通过InputElement::setValueFromRenderer这个函数。
这样HTMLInputElement就获取并记录了用户输入的字符串的信息。
当前就简单的了解下HTMLInputElement的这点基本流程,具体的细节先不看了,有个大概的印象就行了。
分享到:
相关推荐
Android 浏览器(基于WebKit)的源代码
简易web浏览器,基于安卓Webkit开发的。有主页设定、前往、上一页、下一页、刷新、停止载入等基本功能。
WebKit 是一个开源的浏览器引擎,与之相对应的引擎有Gecko(Mozilla Firefox 等使用),Trident(也称MSHTML,IE 使用)和EdgeHTML(也称Chakra,Edge和其他UWP浏览器使用)。同时WebKit 也是苹果Mac OS X 系统引擎...
duilib webkit内核浏览器控件 duilib webkit内核浏览器控件,基于BlaFans的wke内核
因为一些爬虫方面的需求,发现用VS自带的WebBrowser控件,功能和兼容性方面都不能满足要求,所以接触了几个...然后用这几个内核做了一个多核多标签浏览器,即WinForm自带的WebBrowser,WebKit.Net,GeckoFX三个核心。
基于Webkit的新手级浏览器源码是一个简易web浏览器,基于安卓Webkit开发的。
java集成webkit浏览器,内附详细Demo,注意64位需要用64位swt
浏览器的引擎源代码,可编译到不同平台 c++文件
jBrowserDriver是一款采用纯Java编写的无图形化浏览器,基于WebKit, 兼容Selenium WebDriver规范
用DJnative-swt和swt包开发的调用本地浏览器和webkit浏览器的示例
webkit.net 0.5版,c#和winform嵌入chrome核心浏览器控件 原来的sourceforge有时候连不上,特先下载好再上传上来,并带了一个说明,解决了在编译安后时会遇到的:failed to initialize activation context问题。
WebKit技术内幕——朱永盛 完整版 非常适合学习webkit的同学
转webkit内核多页面浏览器,自动填表功能还没实现!请大家测试修改
qt webkit核心的浏览器控件的实例程序
基于QtWebkit开发的浏览器,含历史记录、收藏夹、设置主页等功能!
1. 这是一个基于webkit内核的浏览器。它只有简单的功能,直接调用一个html文件。 2. 使用windown sdk封装的webkit浏览器。 3. demo出自 http://blog.csdn.net/x931100537/article/details/39320149 此demo直接调用...
mbrowser 是一个基于webkit核心开发的嵌入式浏览器,这个是它的源代码win32/wince版本
浏览器内核WebKit编年史.docx
The Nokia Web Browser is built upon S60WebKit, a port of the open source WebKit project to the S60 platform. WebKit contains the WebCore and JavaScriptCore components that Apple uses in its Safari ...
《WebKit技术内幕》从炙手可热的HTML5 的基础知识入手,重点阐述目前应用最广的渲染引擎项目——WebKit。不仅着眼于系统描述WebKit 内部渲染HTML 网页的原理,并基于Chromium 的实现,阐明渲染引擎如何高效地利用...