Chromium for Mac中的BrowserWindow

1引言


     在Chromium for Mac中总有许多类名中包含BrowserWindow的类,如:FramedBrowserWindow, BrowserWindowController, BrowserWindow, BrowserWindowCocoa等,这让我等Chromium新手眼花缭乱。整理此文,帮助记忆区分。


2类图与类


类图如上所示:

         view1系列继承自NSWindow,表示Cocoa中的窗口,其中FramedBrowserWindow类是浏览器的Window;

         view2系列集成自ui::BaseWindow,该接口是一种跨平台的窗口接口,其中BrowserWindowCocoa是BrowserWindow在cocoa上的实现,它以C++的方式桥接Cocoa中的NSWindow,Chromium上的跨平台代码需要操作Browser窗口的时候,需要利用到BrowserWindowCocoa类。说白了BrowserWindowCocoa就是FramedBrowserWindow的一层C++封装;

         model只有一个,就Browser类,它是跨平台的;

         controller系列从NSWindowController一路继承,直到BrowserWindowController。这个controller比较牛X,它的父类(NSWindowController)持有一个NSWindow对象(FramedBrowserWindow对象),它本身持有其它两个(Browser对象和BrowerWindowCocoa对象),不仅如此它还持有其他的各种界面元素的controller(类图未画出),比如  :

         base::scoped_nsobject<ToolbarController> toolbarController_;

         base::scoped_nsobject<TabStripController> tabStripController_;

         base::scoped_nsobject<FindBarCocoaController> findBarCocoaController_; 等。因此可以说BrowserWindowController控制了整个Browser界面。


3窗口的创建和销毁


3.1窗口创建


        虽然BrowserWindowController很牛X,但是我们一般不在自己的代码中直接alloc一个BrowserWindowController,通常的做法是new一个Browser对象,对仅仅是new一个Browser对象,不要也不能delete,虽然这看起来很像memory leak,但也仅仅是看起来,等一下分析原因。

       通常创建窗口的代码如下:

 Browser* browser = new Browser(
      Browser::CreateParams(Browser::TYPE_TABBED, profile, desktop_type));       

      在Browser的构造函数中调用了:

BrowserWindow* BrowserWindow::CreateBrowserWindow(Browser* browser) {
  BrowserWindowController* controller =
      [[BrowserWindowController alloc] initWithBrowser:browser];
  return [controller browserWindow];
}

      该函数创造了一个BrowserWindowController对象,而且在mrc模式下面居然没有设置autorelease,这又很奇怪,感觉这个controller对象好像不会被析构的样子,暂时留下悬念,后面解答。

      再来看看initWithBrowser这个函数干啥了:

- (id)initWithBrowser:(Browser*)browser {
  return [self initWithBrowser:browser takeOwnership:YES];
}
- (id)initWithBrowser:(Browser*)browser takeOwnership:(BOOL)ownIt {  
   if ((self = [super initTabWindowControllerWithTabStrip:hasTabStrip])) {
        //other code...
        browser_.reset(browser);
        //other code...
        windowShim_.reset(new BrowserWindowCocoa(browser, self));
        //other code...
   }
        //other code...
}

       initWithBrowser这个函数调用了initWithBrowser: takeOwnership: ;这个函数有3点值得注意:

      (1)initTabWindowControllerWithTabStrip:这个函数来自它的父类TabWindowController,该函数里面会alloc一个FramedBrowserWindow对象,以scoped_nsobject管理,而且会把controller的window­_设置为 该FramedBrowserWindow对象。

     (2)browser_.reset(browser)这行代码;browser­_是scoped_ptr<Browser>类型的类成员,而它传入的browser也就是我们最开始new的那个Browser对象的指针,这里用scoped_ptr把这个对象管理起来了,因此我们最开始的代码不用也不能delete,而不会发生内存泄漏。现在内存的管理权转移到controller对象身上了(但是我们刚才发现那个controller对象并没有被设置为autorelease,等一下讨论)。

     (3)该函数还有windowShim_.reset(new windowShim_.reset(new BrowserWindowCocoa(browser, self));这行代码,它创造了一个BrowserWindowCocoa对象。并且用scoped_ptr管理起来了。

     至此,窗口创建的过程基本明朗了,

     1 new 一个Browser对象;

     2 在Browser对象构造的过程中alloc && init一个BrowserWindowController对象;

     3 BrowserWindowController对象init干了3件重要的事情:

        3.1 调用其父类函数initTabWindowControllerWithTabStrip alloc && init一     个FramedBrowserWindow对象 并且把该对象设置为controller的window_;

       3.2 把最开始new的那个Browser对象用scoped­_ptr管理了起来;

       3.3 new了一个BrowserWindowCocoa对象并用scoped­_ptr管理起来;


3.2窗口的销毁


     再来谈一下窗口的销毁,当窗口收到关闭消息时候,会调用

void Browser::CloseFrame() {
  window_->Close();
}

      这个window_是BrowserWinodw*,指向的上我们创建的时候new的那个BrowserWindowCocoa对象,(就是在BrowserWindowController中用scoped_ptr管理起来的那个), BrowserWindowCocoa重写了Close()函数,该函数又会调用[window() close];这个window()函数返回[control_ window]也就是我们在创建窗口3.1中alloc && init的那个FramedBrowserWindow对象。现在close消息被传递到了FramedBrowserWindow对象,该消息沿着view1系列类直接往上传递,直到NSWindow类才响应close消息。close会 post NSWindowWillCloseNotification notification到default notification center。又因为BrowserWindowController的继承链上实现了NSWindowDelegate,因此这时会调用windowWillClose:;该函数中又 

[self performSelector:@selector(autorelease)
           withObject:nil
           afterDelay:0];

这个函数会给self发出autorelease消息,把自己注册到autorelease pool上去。这里的self就是BrowserWindowController对象本身,也就是我们在创建窗口的时候alloc和 init的那个对象。这也解释了我们在创建窗口时的那个疑惑,当时alloc的对象直到现在才加入autorelease pool的。

     回顾一下窗口关闭的整个流程

     1 Browser调用CloseFrame();

     2 FramedBrowserWindow对象收到close消息,并且发出NSWindowWillCloseNotification notification;

     3 BrowserWindowController对象作为 FramedBrowserWindow的delegate收到该notification,把self注册到autorelease pool上等待析构。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要调试 Chromium for Android 源代码,需要使用 Android Studio 和 Chromium for Android 源代码。以下是步骤: 1. 下载 Chromium for Android 源代码 从 Chromium 的官方网站上下载 Chromium for Android 源代码。下载完成后,解压到本地。 2. 安装 Android Studio 从 Android Studio 的官方网站上下载最新版本的 Android Studio。安装完成后,打开 Android Studio。 3. 导入 Chromium for Android 项目 在 Android Studio ,选择 File -> New -> Import Project。在弹出的窗口,选择 Chromium for Android 源代码所在的文件夹。然后按照向导完成项目导入。 4. 配置 Chromium for Android 项目 在 Android Studio ,打开 Project Structure 窗口。选择 app 模块,并在 Dependencies 标签页添加 Chromium for Android 的依赖库。然后在 Build Variants 标签页选择正确的 Build Variant。 5. 配置 Chromium for Android 运行环境 在 Android Studio ,打开 Run/Debug Configurations 窗口。点击左上角的加号,添加一个新的 Android Application 配置。在 Configuration 标签页选择正确的模块和启动 Activity。然后在 Profiling 标签页选择正确的调试方式。最后点击 OK 保存配置。 6. 启动调试 在 Android Studio ,点击 Run 按钮启动调试。如果一切正常,就会在设备或模拟器上启动 Chromium for Android 应用,并进入调试模式。 以上就是调试 Chromium for Android 源代码的步骤。需要注意的是,由于 Chromium for Android 是一个庞大而复杂的项目,调试起来可能比较困难,需要具备一定的 Android 开发和调试经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值