记录为了怕自己以后忘记了。
最近在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的时候就已经明白了(不明白同学得自己去看了,那是一大块内容,一时半会将不明白).
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
inBrowser : (浏览器 * ) 浏览器
anchoredAt : ( NSPoint ) anchoredAt
arrowLocation : ( info_bubble :: BubbleArrowLocation )
arrowLocation
DEVMODE : ( BOOL ) { DEVMODE 扩展 :: ExtensionViewHost * 主机 =
扩展 :: ExtensionViewHostFactory :: CreatePopupHost ( URL , 浏览器) ;
D检查 ( 主机) ;
如果 ( ! 主机)
返回nil ; [ gPopup 关闭窗口] ; gPopup = [ [ ExtensionPopupController 的alloc ]
initWithHost : 主机
parentWindow : 浏览器 - > 窗口 ( ) - > GetNativeWindow ( )
anchoredAt : anchoredAt
arrowLocation : arrowLocation
DEVMODE : DEVMODE ] ;
返回 gPopup ;
}