zoukankan      html  css  js  c++  java
  • chromium ④

     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和控件系统了,这几点将是我们后面研究的重点。
  • 相关阅读:
    痞子衡嵌入式:在i.MXRT启动头FDCB里调整Flash工作频率也需同步设Dummy Cycle (以IS25WP128为例)
    《痞子衡嵌入式半月刊》 第 29 期
    痞子衡嵌入式:从头开始认识i.MXRT启动头FDCB里的lookupTable
    痞子衡嵌入式:MCUXpresso IDE下在线调试时使用不同复位策略的现象总结
    痞子衡嵌入式:关于恩智浦入驻B站的一些思考
    《痞子衡嵌入式半月刊》 第 28 期
    痞子衡嵌入式:分享一个i.MXRT系列配套DRAM压力测试上位机工具(i.MXRT DRAM Tester)
    痞子衡嵌入式:在i.MXRT1060-EVK上利用memtester程序给SDRAM做压力测试
    痞子衡嵌入式:内存读写正确性压力测试程序(memtester)
    痞子衡嵌入式:盘点国内MCU级RISC-V内核IP厂商
  • 原文地址:https://www.cnblogs.com/dhsz/p/9252746.html
Copyright © 2011-2022 走看看