Chromium for Mac中的BrowserWindow

来源:互联网 发布:狗狗 知乎 编辑:程序博客网 时间:2024/06/05 06:34

1引言


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


2类图与类


类图如上所示:

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

         view2系列集成自ui::BaseWindow,该接口是一种跨平台的窗口接口,其中BrowserWindowCocoaBrowserWindowcocoa上的实现,它以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管理,而且会把controllerwindow­_设置为 该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
原创粉丝点击