加载中…
正文 字体大小:

chromium源码学习笔记(2) -- test_shell

(2013-02-02 20:08:08)
标签:

webkit

chrome

test_shell

it

分类: webkit
    chromium的源码非常大,选择合适的点入手能省不少力气。在win7下编译chromium中我曾提到学习chromium源码的一个小工程test_shell,代码目录在src/webkit/tools/test_shell下,打开src/webkit下的webkit.sln工程,在webkit下就能看到test_shell。test_shell是一个测试程序,代码和流程都很简单,这篇笔记主要理清test_shell中的主流程和逻辑,为后面学习webkit打好基础,同时,我们也研究一下google的桌面程序都有哪些特点。

    打开test_shell_main.cc文件,找到main函数逐行分析。(windows环境)
    
    base::debug::EnableInProcessStackDumping();
    这句使程序生成crash dump,并将标准输出attach到控制台。具体参考SetUnhandledExceptionFilter API函数。
    base::EnableTerminationOnHeapCorruption();
    当堆越界或出错时终止进程,winxp sp3以上版本才支持。具体参考HeapSetInformation API函数。

    base::AtExitManager at_exit_manager;
    AtExitManager目的是执行类似atexit的动作,它采用后进先出的栈结构运行注册一系列的任务,当对象析构时会执行任务列表,最常用的是执行base::Singleton类型对象的销毁动作,可以看到Singleton的实现中如果有kRegisterAtExit属性,则自动将OnExit函数作为任务添加到AtExitManager中,这样,我们不但能在程序结束时指定Singleton对象的销毁顺序,还能定义更多动作来让AtExitManager帮助管理执行。

    TestShellPlatformDelegate::PreflightArgs(&argc, &argv);
    根据注释这一句使程序有机会提前根据OS处理一些命令行,并过滤掉一些特有命令。不深究。

    CommandLine::Init(argc, argv);
    const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
    这两句建立一个命令行解析对象,将命令行解释为一个命令列表。后续很多处理都根据parsed_command_line对象的解释结果,配置不同的功能和支持。关于后续不同配置的执行,不再一一详述。

    TestShellPlatformDelegate platform(parsed_command_line);
    为跨平台做的一些逻辑的代理,比如后续的platform.CheckLayoutTestSystemDependencies(),platform.SuppressErrorReporting(),platform.InitializeGUI()platform.SelectUnifiedTheme()等调用,会检查、收集系统默认字体、字号、主题风格等UI相关的信息,并完成窗口注册等工作。多数为方便测试用,不深究。

    MessageLoopForUI main_message_loop;
    这行代码看似简单,却包含了chromium中线程和消息循环机制的精髓。test_shell工程中只是用来初始化一些状态,并未真正用到。简单来说,MessageLoop是为不同平台线程事件处理做的封装,MessageLoopForUI面向UI线程,对于windows来说,它是对Win32窗口的消息队列和循环机制做的封装。关于MessageLoop后续会有专门一篇来研究它。

    后面的数行代码全都是根据平台环境和命令行确定程序细节功能点,比如v8错误是否abort、窗口风格、加速渲染、url默认加载次数、http cache模式、html5支持等,先略过。

    TestShellWebKitInit test_shell_webkit_init(layout_test_mode);
    初始化webkit,配置webkit的各种参数。先略过。

    icu_util::Initialize();
    初始化icu,icu是一个为C/C++和Java语言提供Unicode和国际化支持的库,参考ICU - International Components for Unicode。chromium将它做为第三方库来支持Unicode。

    net::NetModule::SetResourceProvider(TestShell::ResourceProvider);
    为network模块设置资源句柄。由于浏览器对本地资源的访问是有限制的,chromium通过NetModule来管理network对本地资源的访问。以后再详细研究。

    platform.InitializeGUI();
    还记得前面提到的platform对象吗,这句为GUI初始化环境。对于windows来说,内部调用InitCommonControlsEx初始化标准控件风格,并完成窗口类注册,终于找到熟悉的代码了,呵呵。

    TestShell::InitializeTestShell(layout_test_mode, allow_external_pages);
    初始化test_shell程序。看代码主要初始化了ole、window list、resource等,同时根据command line设置crash dump,这里用到了google的crash开源处理框架breakpad,之前关于程序崩溃处理的博文中有介绍。

    GURL starting_url;
    GURL是对url的封装类,test_shell启动时会加载该url,其值在我这里为:“file:///D:/chromium/home/src_tarball/tarball/chromium/src/webkit/data/test_shell/index.htm”。

    std::string stats_filename = kStatsFilePrefix +
      base::Uint64ToString(base::RandUint64() & 0xFFFFFFFFL);
    RemoveSharedMemoryFile(stats_filename);
    base::StatsTable *table = new base::StatsTable(stats_filename,
      kStatsFileThreads,
      kStatsFileCounters);
    base::StatsTable::set_current(table);
    设置用于统计的stats table。stats table生成一个共享内存的随机名来保证不同实例的唯一性,内部通过一个hash表对刚兴趣的项进行计数。

    下面这几行代码就是窗口创建和运行的代码了:
    TestShell* shell;
    if (TestShell::CreateNewWindow(starting_url, &shell)) {
      shell->Show(WebKit::WebNavigationPolicyNewWindow);

      if (parsed_command_line.HasSwitch(test_shell::kDumpStatsTable))
        shell->DumpStatsTableOnExit();

      webkit_glue::SetJavaScriptFlags(TestShell::GetJSFlagsForLoad(0));
      MessageLoop::current()->Run();
    }
    TestShell类是对test_shell app的封装,前面已经调用过很多TestShell的静态函数了,比如一系列的config设置、TestShell::InitLoggingTestShell::InitializeTestShell等。通过调用TestShell::CreateNewWindow函数,shell变量被实例化,实际上内部是通过调用Initialize()函数完成,在windows下主要是创建主窗口m_mainWnd以及初始化主界面,包括“Back”、“Forward”、“Reload”、“Stop”四个按钮和URL编辑框,之后创建一个webview窗口并load url显示内容。
    MessageLoop::current()->Run();一句封装了主消息循环,内部通过base::RunLoop的run函数完成,最终将调用到MessagePumpForUI::DoRunLoop中,DoRunLoop基本就是对消息循环的封装。
    当收到WM_QUIT消息时,消息循环结束,Run函数返回。经过几个函数的清理工作后,main函数结束。

    以上就是整个test_shell的主流程,看上去代码逻辑还是非常清晰的。真正的chromium逻辑比test_shell肯定要复杂,但大致类似。可以看到chromium的代码面向对象的封装做的非常好,比如AtExitManager对退出逻辑的封装、MessageLoop对消息循环以及跨平台的包装等。另外可以看到对command line的封装和处理占了很多语句,还有config、log、crash、statistic等的支持,这些是所有application都需要的部分,值得研究和学习。
    从对主流程的学习可以看到,涉及webkit的代码并不多,主要由TestShellWebKitInit和webkit_glue两个封装完成。另外比较重要的部分就是MessageLoop、跨平台以及UI和控件系统了,这几点将是我们后面研究的重点。


0

阅读 评论 收藏 转载 喜欢 打印举报
已投稿到:
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4006900000 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有