[Mac]extension弹出窗口的实现

来源:互联网 发布:中国最好的云计算公司 编辑:程序博客网 时间:2024/05/24 02:16

记录为了怕自己以后忘记了。

最近在chromium解了几个extension的bug,顺便把这块整理一下.


1. UI方面,弹出的是一个 NSWindow,   对应的代码是 NSExtensionPopupController : BaseBubbleController

     scoped_ptr<extension::ExtensionViewHost> host_;

    NSExtensionPopupController的作用是: 

              1) 控制NSWindow的显示以及关闭,即一个正常Bubble应该有的动作。例如 当你点击popup窗口外的地方,会关闭(这部分功能是继承与 BaseBubbleController的)

              2) 在合适的时候,把 extension的内容放到合适的位置显示.


 一般显示的时候,是直接调用静态函数的 

+ (ExtensionPopupController*)showURL:(GURL)url                           inBrowser:(Browser*)browser                          anchoredAt:(NSPoint)anchoredAt                       arrowLocation:(info_bubble::BubbleArrowLocation)                                         arrowLocation                             devMode:(BOOL)devMode {  extensions::ExtensionViewHost* host =               //根据url 和 browser 来创建一个 ExtensionViewHost      extensions::ExtensionViewHostFactory::CreatePopupHost(url, browser);  DCHECK(host);  if (!host)    return nil;  ...  [gPopup close]; // 关闭之前的popup,默认是只显示一个extension的popup  ...  gPopup = [[ExtensionPopupController alloc]            // 创建新的popup的controller      initWithHost:host      parentWindow:browser->window()->GetNativeWindow()        anchoredAt:anchoredAt     arrowLocation:arrowLocation           devMode:devMode];  return gPopup;}


那么当ExtensionPopupController创建的时候,他已经拥有了他需要的 ExtensionViewHost. 以及BaseBubbleController一些需要的参数,例如箭头位置.

现在又2个问题:

     1)  ExtensionViewHost 是什么,作用是什么?

         C++代码层的view,是真正要在Popup中显示内容的view

     2)ExtensionPopupController 那么具体他干了什么呢?

           ExtensionPopupController 有2个成员变量,一个是 extension::ExtensionViewHost host_,另外一个是 NSView* extensionView_.

           看下他初始化

  

- (id)initWithHost:(extensions::ExtensionViewHost*)host      parentWindow:(NSWindow*)parentWindow        anchoredAt:(NSPoint)anchoredAt     arrowLocation:(info_bubble::BubbleArrowLocation)arrowLocation           devMode:(BOOL)devMode {
  base::scoped_nsobject<InfoBubbleWindow> window([[InfoBubbleWindow alloc]      initWithContentRect:ui::kWindowSizeDeterminedLater                styleMask:NSBorderlessWindowMask                  backing:NSBackingStoreBuffered                    defer:YES]);     // 创建一个 InfoBubbleWindow,最终是作为BaseBubble的window  if (!window.get())    return nil;  anchoredAt = [parentWindow convertBaseToScreen:anchoredAt];  if ((self = [super initWithWindow:window   // 看上面的注释                       parentWindow:parentWindow                         anchoredAt:anchoredAt])) {    host_.reset(host);    beingInspected_ = devMode;    ignoreWindowDidResignKey_ = NO;    InfoBubbleView* view = self.bubble;   // 获取自己的显示内容的view,其实就是NSWindow的 contentView    [view setArrowLocation:arrowLocation];    extensionView_ = host->view()->native_view();   // 这里,把c++的view 与cocoa的算是联系上了,看下面也有介绍    container_.reset(new ExtensionPopupContainer(self));    host->view()->set_container(container_.get());  // 把 view 设置了 container    NSNotificationCenter* center = [NSNotificationCenter defaultCenter];    [center addObserver:self               selector:@selector(extensionViewFrameChanged)                   name:NSViewFrameDidChangeNotification                 object:extensionView_];    [view addSubview:extensionView_];  // 把 extensionView 加入到这个window的 contentView里    notificationBridge_.reset(new DevtoolsNotificationBridge(self));    registrar_.reset(new content::NotificationRegistrar);    if (beingInspected_) {      // Listen for the extension to finish loading so the dev tools can be      // opened.      registrar_->Add(notificationBridge_.get(),                      chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,                      content::Source<BrowserContext>(host->browser_context()));    }  }  return self;}

看完初始化,估计会oc的人明白差不多了,大体就是说,

c++有view的,他是显示内容的提供者,就是 ExtensionViewHost, 要显示在mac上,他打开一个 NSWindow,然后把 ExtensionViewHost里的真正的view设置为NSWindow的contentView的一个子View,然后就可以画出了,同时用户如果操作或者别的 影响了这个window,比如frame变化,或者widow关闭了,这里会有相应的处理,返回通知host_以让c++侧代码得以反应.


2. 其实这里重点想说下 ExtensionHostView 以及如何去建立 renderer process 去运行extension的.

   在上面showURL已经看到

    extensions::ExtensionViewHostFactory::CreatePopupHost(url, browser);

   返回的是  ExtensionViewHostMac.

   ExtensionViewHostMac : public ExtensionViewHost

   ExtensionViewHostMac 几乎啥都没做吧

   

  // ExtensionViewHost 是在browser ui线程里来backing一个view用的,例如,可以是popup,infobar, dialog

   ExtensionViewHost: public ExtensionHost, 

                                 public web_modal::WebContentsModalDialogManagerDelegate,

                                 public web_modal::WebContentsModalDialogHost

  重要成员变量:

  scoped_ptr<PlatformExtensionView> view_;  // 这里是 ExtensionViewMac , typdef的,上面代码里 extensionView_ = host->view()->native_view().

                                                                   // ExtensionViewMac 其实是一个桥梁,是mac 和 c++代码的桥梁



  如何建立起rederer process,需要看 ExtensionHost


ExtensionHost::ExtensionHost(const Extension* extension,                             SiteInstance* site_instance,                             const GURL& url,                             ViewType host_type)    : delegate_(ExtensionsBrowserClient::Get()->CreateExtensionHostDelegate()),      extension_(extension),      extension_id_(extension->id()),      browser_context_(site_instance->GetBrowserContext()),      render_view_host_(NULL),      did_stop_loading_(false),      document_element_available_(false),      initial_url_(url),      extension_function_dispatcher_(browser_context_, this),      extension_host_type_(host_type) {  // Not used for panels, see PanelHost.  DCHECK(host_type == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE ||         host_type == VIEW_TYPE_EXTENSION_DIALOG ||         host_type == VIEW_TYPE_EXTENSION_INFOBAR ||         host_type == VIEW_TYPE_EXTENSION_POPUP);  host_contents_.reset(WebContents::Create(              // 又见到熟悉的 WebContents::Create      WebContents::CreateParams(browser_context_, site_instance))),  content::WebContentsObserver::Observe(host_contents_.get());  host_contents_->SetDelegate(this);  SetViewType(host_contents_.get(), host_type);  render_view_host_ = host_contents_->GetRenderViewHost();  // Listen for when an extension is unloaded from the same profile, as it may  // be the same extension that this points to.  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,                 content::Source<BrowserContext>(browser_context_));  // Set up web contents observers and pref observers.  delegate_->OnExtensionHostCreated(host_contents());}

我觉的,当我们看到 WebContents::Create的时候就已经明白了(不明白同学得自己去看了,那是一大块内容,一时半会将不明白).





-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

0 0
原创粉丝点击