准备
在开始之前,要按照chromium官方网站的做法:准备好开发环境,下载代码等,具体请参见:
windows编译指南。
用webkit.org的代码来调试和熟悉webkit,在windows上有点困难,查了不少资料,自己也想了些办法,后来发现chromium提供了一个content_shell项目可以让初学者熟悉webkit;打开chrome解决方案(在src/chrome目录下),找到content_shell,并设为启动项目。如下图:
设置调试参数
content_shell项目默认也是多进程的,为了更好的熟悉webkit,建议用单进程来调试,使用如下参数即可:
--user-data-dir=c:\tmp\my_debug_profile --single-process --renderer-startup-dialog --no-sandbox,当然你可以改动相关的目录。如下图所示:
设置断点和调试:
用vs2010打开page.cpp文件,在src/third_party/webkit/source/webcore/page目录下,找到page类的构造函数:
Page::Page(PageClients& pageClients)
: m_chrome(Chrome::create(this, pageClients.chromeClient))
, m_dragCaretController(DragCaretController::create())
#if ENABLE(DRAG_SUPPORT)
, m_dragController(DragController::create(this, pageClients.dragClient))
#endif
, m_focusController(FocusController::create(this))
#if ENABLE(CONTEXT_MENUS)
, m_contextMenuController(ContextMenuController::create(this, pageClients.contextMenuClient))
#endif
#if ENABLE(INSPECTOR)
, m_inspectorController(InspectorController::create(this, pageClients.inspectorClient))
#endif
#if ENABLE(POINTER_LOCK)
, m_pointerLockController(PointerLockController::create(this))
#endif
, m_settings(Settings::create(this))
, m_progress(ProgressTracker::create())
, m_backForwardController(BackForwardController::create(this, pageClients.backForwardClient))
, m_theme(RenderTheme::themeForPage(this))
, m_editorClient(pageClients.editorClient)
, m_validationMessageClient(pageClients.validationMessageClient)
, m_subframeCount(0)
, m_openedByDOM(false)
, m_tabKeyCyclesThroughElements(true)
, m_defersLoading(false)
, m_defersLoadingCallCount(0)
, m_inLowQualityInterpolationMode(false)
, m_cookieEnabled(true)
, m_areMemoryCacheClientCallsEnabled(true)
, m_mediaVolume(1)
, m_pageScaleFactor(1)
, m_deviceScaleFactor(1)
, m_suppressScrollbarAnimations(false)
, m_didLoadUserStyleSheet(false)
, m_userStyleSheetModificationTime(0)
, m_group(0)
, m_debugger(0)
, m_customHTMLTokenizerTimeDelay(-1)
, m_customHTMLTokenizerChunkSize(-1)
, m_canStartMedia(true)
, m_viewMode(ViewModeWindowed)
, m_minimumTimerInterval(Settings::defaultMinDOMTimerInterval())
, m_timerAlignmentInterval(Settings::defaultDOMTimerAlignmentInterval())
, m_isEditable(false)
, m_isOnscreen(true)
#if ENABLE(PAGE_VISIBILITY_API)
, m_visibilityState(PageVisibilityStateVisible)
#endif
, m_displayID(0)
, m_layoutMilestones(0)
, m_isCountingRelevantRepaintedObjects(false)
#ifndef NDEBUG
, m_isPainting(false)
#endif
, m_alternativeTextClient(pageClients.alternativeTextClient)
, m_scriptedAnimationsSuspended(false)
{
ASSERT(m_editorClient);
if (!allPages) {
allPages = new HashSet<Page*>;
networkStateNotifier().setNetworkStateChangedFunction(networkStateChanged);
}
ASSERT(!allPages->contains(this));
allPages->add(this);
#ifndef NDEBUG
pageCounter.increment();
#endif
}
在红色标记处设置断点,你也可以在该函数的其他地方设置断点,ok,按F5就可以看到如下结果了,一个调用堆栈的copy:
webkit.dll!WebCore::Page::Page(WebCore::Page::PageClients & pageClients) 行 152 C++
webkit.dll!WebKit::WebViewImpl::WebViewImpl(WebKit::WebViewClient * client) 行 450 + 0x26 字节 C++
webkit.dll!WebKit::WebView::create(WebKit::WebViewClient * client) 行 264 + 0x29 字节 C++
content.dll!content::RenderViewImpl::Initialize(content::RenderViewImplParams * params) 行 711 + 0x30 字节 C++
content.dll!content::RenderViewImpl::Create(int opener_id, const content::RendererPreferences & renderer_prefs, const WebPreferences & webkit_prefs, base::RefCountedData<int> * counter, int routing_id, int surface_id, __int64 session_storage_namespace_id, const std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > & frame_name, bool is_renderer_created, bool swapped_out, int next_page_id, const WebKit::WebScreenInfo & screen_info, AccessibilityMode accessibility_mode, bool allow_partial_swap) 行 931 C++
content.dll!content::RenderThreadImpl::OnCreateNewView(const ViewMsg_New_Params & params) 行 1207 + 0xca 字节 C++
content.dll!DispatchToMethod<content::RenderThreadImpl,void (__thiscall content::RenderThreadImpl::*)(ViewMsg_New_Params const &),ViewMsg_New_Params>(content::RenderThreadImpl * obj, void (const ViewMsg_New_Params &)* method, const Tuple1<ViewMsg_New_Params> & arg) 行 546 + 0xf 字节 C++
content.dll!ViewMsg_New::Dispatch<content::RenderThreadImpl,content::RenderThreadImpl,void (__thiscall content::RenderThreadImpl::*)(ViewMsg_New_Params const &)>(const IPC::Message * msg, content::RenderThreadImpl * obj, content::RenderThreadImpl * sender, void (const ViewMsg_New_Params &)* func) 行 785 + 0x82 字节 C++
content.dll!content::RenderThreadImpl::OnControlMessageReceived(const IPC::Message & msg) 行 1179 + 0x84 字节 C++
content.dll!content::ChildThread::OnMessageReceived(const IPC::Message & msg) 行 269 + 0x13 字节 C++
ipc.dll!IPC::ChannelProxy::Context::OnDispatchMessage(const IPC::Message & message) 行 261 + 0x18 字节 C++
> ipc.dll!base::internal::RunnableAdapter<void (__thiscall IPC::ChannelProxy::Context::*)(IPC::Message const &)>::Run(IPC::ChannelProxy::Context * object, const IPC::Message & a1) 行 190 + 0x21 字节 C++
ipc.dll!base::internal::InvokeHelper<0,void,base::internal::RunnableAdapter<void (__thiscall IPC::ChannelProxy::Context::*)(IPC::Message const &)>,void __cdecl(IPC::ChannelProxy::Context * const &,IPC::Message const &)>::MakeItSo(base::internal::RunnableAdapter<void (__thiscall IPC::ChannelProxy::Context::*)(IPC::Message const &)> runnable, IPC::ChannelProxy::Context * const & a1, const IPC::Message & a2) 行 900 C++
ipc.dll!base::internal::Invoker<2,base::internal::BindState<base::internal::RunnableAdapter<void (__thiscall IPC::ChannelProxy::Context::*)(IPC::Message const &)>,void __cdecl(IPC::ChannelProxy::Context *,IPC::Message const &),void __cdecl(IPC::ChannelProxy::Context *,IPC::Message)>,void __cdecl(IPC::ChannelProxy::Context *,IPC::Message const &)>::Run(base::internal::BindStateBase * base) 行 1257 + 0x2a 字节 C++
base.dll!base::Callback<void __cdecl(void)>::Run() 行 396 + 0xe 字节 C++
base.dll!base::MessageLoop::RunTask(const base::PendingTask & pending_task) 行 486 C++
base.dll!base::MessageLoop::DeferOrRunPendingTask(const base::PendingTask & pending_task) 行 499 C++
base.dll!base::MessageLoop::DoWork() 行 688 + 0xc 字节 C++
base.dll!base::MessagePumpForUI::DoRunLoop() 行 241 + 0x1d 字节 C++
base.dll!base::MessagePumpWin::RunWithDispatcher(base::MessagePump::Delegate * delegate, base::MessagePumpDispatcher * dispatcher) 行 64 + 0xf 字节 C++
base.dll!base::MessagePumpWin::Run(base::MessagePump::Delegate * delegate) 行 48 + 0x1c 字节 C++
base.dll!base::MessageLoop::RunInternal() 行 441 + 0x29 字节 C++
base.dll!base::MessageLoop::RunHandler() 行 415 C++
base.dll!base::RunLoop::Run() 行 46 C++
base.dll!base::MessageLoop::Run() 行 322 C++
base.dll!base::Thread::Run(base::MessageLoop * message_loop) 行 160 C++
base.dll!base::Thread::ThreadMain() 行 204 + 0x16 字节 C++
base.dll!base::`anonymous namespace'::ThreadFunc(void * params) 行 57 + 0xe 字节 C++
从上面的图可以看出:多进程变成了多线程,IPC照样存在,只是在同一个进程中。也验证了一个webview对应一个page的说法。
其中过程,我们可以对照源码细细体会。
相关类图
这里我想介绍chromium webkit port的几个核心抽象类:见图,这样有助于理解
在这个类图中,我们可以看到WebView(WebViewImpl)起到了桥梁的作用,通过它把WebViewClient、ChromeClient和page联系起来了。