webkit调试之二--初始化frame

本文详细解析了初始化frame的过程,重点介绍了WebFrameImpl类在Chromium和WebKit之间的沟通作用,从初始化page到创建frame,再到初始化mainFrame的整个流程,并通过相关类图展示其关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

调用堆栈

在看这篇文章前,请参见webkit调试之一 --初始化page

第一步讲述了初始化page的工作,现在我们来看看初始化frame的工作

看看call stack

 	webkit.dll!WebCore::Page::setMainFrame(WTF::PassRefPtr<WebCore::Frame> mainFrame)  行 247	C++
 	webkit.dll!WebCore::Frame::create(WebCore::Page * page, WebCore::HTMLFrameOwnerElement * ownerElement, WebCore::FrameLoaderClient * client)  行 191	C++
 	webkit.dll!WebKit::WebFrameImpl::initializeAsMainFrame(WebCore::Page * page)  行 2166 + 0x16 字节	C++
 	webkit.dll!WebKit::WebViewImpl::initializeMainFrame(WebKit::WebFrameClient * frameClient)  行 311	C++
>	content.dll!content::RenderViewImpl::Initialize(content::RenderViewImplParams * params)  行 763 + 0x4e 字节	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++

相关类图:


可以看到WebFrameImpl起到了沟通chromiumhe webkit的桥梁作用。

// bancai.js $(document).ready(function () { const modal = new bootstrap.Modal('#bancaiModal'); let currentMode = 'view'; let caizhiList = []; let mupiList = []; let currentSearchText = ''; // 从父窗口获取 DataManager let dataManager = null; // 等待父窗口的 DataManager 准备就绪 async function waitForDataManager() { return new Promise((resolve, reject) => { if (window.parent && window.parent.dataManager) { resolve(window.parent.dataManager); } else { reject(new Error('无法从父窗口获取 DataManager')); } }); } // 初始化函数 async function initialize() { try { dataManager = await waitForDataManager(); if (!dataManager || typeof dataManager.fetchAll !== 'function') { throw new Error('无效的 DataManager 实例'); } // 解构需要的方法和属性 const { data, addEntity, updateEntity, deleteEntity, fetchAll } = dataManager; // 确保数据已加载 await fetchAll(); // 更新材质和木皮选项 updateOptions(); // 渲染板材表格 refreshTable(); } catch (error) { console.error('初始化失败:', error); alert('系统初始化失败,请刷新页面或联系管理员'); } } // 更新材质和木皮选项 function updateOptions() { caizhiList = data.caizhis; updateSelectOptions('#caizhiSelect', caizhiList); mupiList = data.mupis.map(m => ({ ...m, name: m.you ? `${m.name}(油漆)` : m.name, })); updateSelectOptions('#mupi1Select', mupiList); updateSelectOptions('#mupi2Select', mupiList); } // 更新下拉框选项 function updateSelectOptions(selector, data) { $(selector).empty(); data.forEach(item => { $(selector).append(`<option value="${item.id}">${item.name}</option>`); }); } // 刷新表格 function refreshTable() { const filteredData = filterBancais(currentSearchText); renderBancaiTable(filteredData); } // 搜索过滤 function filterBancais(searchText) { if (!searchText) return data.bancais; return data.bancais.filter(bancai => { const caizhiName = bancai.caizhi?.name || ''; const mupi1Name = bancai.mupi1?.name || ''; const mupi2Name = bancai.mupi2?.name || ''; const houdu = bancai.houdu.toString(); return [ caizhiName.toLowerCase(), mupi1Name.toLowerCase(), mupi2Name.toLowerCase(), houdu.toLowerCase(), ].some(field => field.includes(searchText.toLowerCase())); }); } // 渲染表格 function renderBancaiTable(bancais) { const $tbody = $('#bancaiTable tbody'); $tbody.empty(); bancais.forEach(bancai => { const caizhiName = bancai.caizhi?.name || '未知'; const mupi1Name = bancai.mupi1?.name || '未知'; const mupi2Name = bancai.mupi2?.name || '未知'; const row = ` <tr data-id="${bancai.id}"> <td>${bancai.id}</td> <td>${caizhiName}</td> <td>${mupi1Name} ${bancai.mupi1?.you ? '(油漆)' : ''}</td> <td>${mupi2Name} ${bancai.mupi2?.you ? '(油漆)' : ''}</td> <td>${bancai.houdu}</td> <td> <button class="btn btn-sm btn-info view-btn">查看</button> <button class="btn btn-sm btn-warning edit-btn">编辑</button> <button class="btn btn-sm btn-danger delete-btn">删除</button> </td> </tr> `; $tbody.append(row); }); bindTableEvents(); } // 绑定表格事件 function bindTableEvents() { $('.view-btn').click(function () { const id = $(this).closest('tr').data('id'); openModalForBancai(id, 'view'); }); $('.edit-btn').click(function () { const id = $(this).closest('tr').data('id'); openModalForBancai(id, 'edit'); }); $('.delete-btn').click(function () { const id = $(this).closest('tr').data('id'); deleteBancai(id); }); } // 添加按钮事件 $('#addBancaiBtn').click(function () { $('#bancaiForm')[0].reset(); $('#modalTitle').text('添加新板材'); currentMode = 'add'; enableForm(true); updateOptions(); modal.show(); }); // 搜索按钮事件 $('#searchBtn').click(function () { currentSearchText = $('#searchInput').val(); refreshTable(); }); // 输入框实时搜索 $('#searchInput').on('input', function () { currentSearchText = $(this).val(); refreshTable(); }); // 打开弹窗显示板材数据 function openModalForBancai(id, mode) { const bancai = data.bancais.find(b => b.id === id); if (!bancai) return; currentMode = mode; $('#bancaiId').val(bancai.id); $('#caizhiSelect').val(bancai.caizhi.id); $('#mupi1Select').val(bancai.mupi1.id); $('#mupi2Select').val(bancai.mupi2.id); $('#houdu').val(bancai.houdu); $('#modalTitle').text(mode === 'view' ? '板材详情' : '编辑板材'); enableForm(mode === 'edit'); modal.show(); } // 启用/禁用表单 function enableForm(enable) { $('#caizhiSelect').prop('disabled', !enable); $('#mupi1Select').prop('disabled', !enable); $('#mupi2Select').prop('disabled', !enable); $('#houdu').prop('disabled', !enable); $('#saveBtn').toggle(enable); } // 保存按钮点击事件 $('#saveBtn').click(async function () { const formData = { id: $('#bancaiId').val(), caizhiId: parseInt($('#caizhiSelect').val()), mupi1Id: parseInt($('#mupi1Select').val()), mupi2Id: parseInt($('#mupi2Select').val()), houdu: parseFloat($('#houdu').val()), }; try { if (currentMode === 'add') { await addEntity('bancais', formData); } else { await updateEntity('bancais', formData); } refreshTable(); modal.hide(); } catch (error) { console.error('操作失败:', error); alert('操作失败,请重试'); } }); // 删除板材 async function deleteBancai(id) { if (!confirm('确定要删除此板材吗?')) return; try { await deleteEntity('bancais', id); refreshTable(); } catch (error) { console.error('删除失败:', error); alert('删除失败,请重试'); } } // 初始化应用 initialize(); });<!doctype html> <html> <head data-genuitec="wc1-2-10"> <meta charset="utf-8" data-genuitec="wc1-2-11"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" data-genuitec="wc1-2-12"> <title data-genuitec="wc1-2-13">峤丞板材库存管理</title> <meta name="viewport" content="width=device-width, initial-scale=1" data-genuitec="wc1-2-14"> <link rel="stylesheet" type="text/css" href="fonts/font-awesome-4.7.0/css/font-awesome.min.css" data-genuitec="wc1-2-15"> <link rel="stylesheet" type="text/css" href="main/bootstrap-3.3.7-dist/css/bootstrap.css.map" data-genuitec="wc1-2-16"> <link rel="stylesheet" type="text/css" href="css/util.css" data-genuitec="wc1-2-17"> <link rel="stylesheet" type="text/css" href="css/main.css" data-genuitec="wc1-2-18"> <link rel="stylesheet" type="text/css" href="css/index2.css" data-genuitec="wc1-2-19"> <script type="text/javascript" src="js/jquery-3.2.1.min.js" data-genuitec="wc1-2-55"></script> <script type="text/javascript" src="js/jsyilai.js" data-genuitec="wc1-2-56"></script> <script type="module" data-genuitec="wc1-2-57"> // 共享的DataManager类 document.addEventListener('DOMContentLoaded', async () => { try { // 创建实例并挂载到window window.dataManager = new DataManager('http://127.0.0.1:8080/KuCun2'); // 初始化数据 await window.dataManager.fetchAll(); console.log('Data Manager initialized successfully'); // 设置iframe通信 const iframe = document.getElementById('iframeid'); iframe.onload = () => { console.log('Iframe loaded'); // 通知iframe数据已准备好 iframe.contentWindow.postMessage('DataManagerReady', '*'); }; } catch (error) { console.error('Failed to initialize DataManager:', error); } }); </script> <style type="text/css" data-genuitec="wc1-2-20"> *{ margin:0; padding:0; } .frame-header { height: 60px; background-color: #23262E; justify-content: space-between; } .frame-header-li{ font-family: Arial, Helvetica, sans-serif; font-size:40px; } .frame-ul{ } .frame-ul li{ border-style: solid; border-width:1px 0px 1px 0px; margin-top: 1px; height: 35px; text-align: center } #username{ position: absolute; right: 0; /* 靠右 */ } .frame-body { position: fixed; top: 60px; right: 0; bottom: 0; left: 0; display: flex; flex-direction: row; } .frame-side { scrollbar-width: none; /* firefox隐藏滚动条 */ -ms-overflow-style: none; /* IE 10+隐藏滚动条 */ overflow-x: hidden; overflow-y: auto; width: 200px; background-color:#9e5; } .frame-side::-webkit-scrollbar { display: none; /* Chrome Safari 隐藏滚动条*/ } .frame-main { flex-grow: 1; background-color:#fff; } .jiaoluo{ margin: auto; margin-right: 0px; } .menu { display: none; position: absolute; background-color: #f9f9f9; border: 1px solid #ccc; padding: 10px; list-style-type: none; margin: 0; z-index: 10; } </style> <script>"undefined"==typeof CODE_LIVE&&(!function(e){var t={nonSecure:"59356",secure:"59361"},c={nonSecure:"http://",secure:"https://"},r={nonSecure:"127.0.0.1",secure:"gapdebug.local.genuitec.com"},n="https:"===window.location.protocol?"secure":"nonSecure";script=e.createElement("script"),script.type="text/javascript",script.async=!0,script.src=c[n]+r[n]+":"+t[n]+"/codelive-assets/bundle.js",e.getElementsByTagName("head")[0].appendChild(script)}(document),CODE_LIVE=!0);</script></head> <body data-genuitec="wc1-2-8" data-genuitec-lp-enabled="true" data-genuitec-file-id="wc1-2" data-genuitec-path="/KuCun2/src/main/webapp/index.html"> <div class="frame-header" data-genuitec="wc1-2-9" data-genuitec-lp-enabled="true" data-genuitec-file-id="wc1-2" data-genuitec-path="/KuCun2/src/main/webapp/index.html"> <a class='frame-header-li' style="color:#fff" data-genuitec="wc1-2-21">峤丞木材仓库管理</a> <a id="username" class='frame-header-li' style="color:#520" data-genuitec="wc1-2-22">峤丞木材仓库管理</a> <ul class="menu" data-genuitec="wc1-2-23"> <li data-genuitec="wc1-2-24">选项 1</li> <li data-genuitec="wc1-2-25">选项 2</li> <li data-genuitec="wc1-2-26">选项 3</li> </ul> </div> <div class="frame-body" data-genuitec="wc1-2-27"> <div class="frame-side" data-genuitec="wc1-2-28"> <ul id="main_u" class='frame-ul' style="text-align:center;" data-genuitec="wc1-2-29"> <li data-genuitec="wc1-2-30"><a href="main/test.html" target="main" data-genuitec="wc1-2-31">首页</a></li> <li data-genuitec="wc1-2-32"><a href="main/dingdan.html" target="main" data-genuitec="wc1-2-33">订单查询</a></li> <li data-genuitec="wc1-2-34"><a href="main/bancai.html" target="main" data-genuitec="wc1-2-35">板材查询</a></li> <li data-genuitec="wc1-2-36"><a href="main/Guanli.html" target="main" data-genuitec="wc1-2-37">人员管理</a></li> <li data-genuitec="wc1-2-38"><a href="main/test.html" target="main" data-genuitec="wc1-2-39">test</a></li> <li data-genuitec="wc1-2-40"><a href="main/tianjia.html" target="main" data-genuitec="wc1-2-41">test</a></li> </ul> </div> <div class="frame-main" data-genuitec="wc1-2-42"> <iframe id="iframeid" name="main" src="main/bancai.html" width="100%" height="100%" frameborder="0" data-genuitec="wc1-2-43"> </iframe> </div> </div> </body> </html>/** * 数据管理器类,负责与后端API通信并管理数据 */ class DataManager { constructor(baseUrl) { this.baseUrl = baseUrl; this.data = { bancais: [], dingdans: [], mupis: [], chanpins: [], kucuns: [], dingdan_chanpin_zujians: [], chanpin_zujians: [], zujians: [], caizhis: [], dingdan_chanpins: [], users: [] }; this.isSyncing = false; this.lastSync = null; // 回调注册表 this.callbacks = { // 全局回调 all: [], // 按实体类型分类的回调 bancais: [], dingdan: [], mupi: [], chanpin: [], kucun: [], dingdan_chanpin_zujian: [], chanpin_zujian: [], zujian: [], caizhi: [], dingdan_chanpin: [], user: [] // ...其他实体 }; } /** * 获取所有数据 * @returns {Promise<boolean>} 是否成功 */ async fetchAll() { try { const response = await fetch(`${this.baseUrl}/app/all`); if (!response.ok) throw new Error('Network response was not ok'); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || 'API error'); // 更新本地数据 Object.keys(this.data).forEach(key => { if (result.data[key]) { this.data[key] = result.data[key]; } }); this.lastSync = new Date(); return true; } catch (error) { console.error('Fetch error:', error); return false; } } /** * 注册回调函数 * @param {string} entity - 实体类型(如'bancai')或'all'表示全局回调 * @param {Function} callback - 回调函数,参数为(operation, data) */ registerCallback(entity, callback) { if (!this.callbacks[entity]) { this.callbacks[entity] = []; } this.callbacks[entity].push(callback); } /** * 移除回调函数 * @param {string} entity - 实体类型 * @param {Function} callback - 要移除的回调函数 */ unregisterCallback(entity, callback) { if (!this.callbacks[entity]) return; const index = this.callbacks[entity].indexOf(callback); if (index !== -1) { this.callbacks[entity].splice(index, 1); } } /** * 触发回调 * @param {string} operation - 操作类型('add', 'update', 'delete') * @param {string} entity - 实体类型 * @param {Object} data - 相关数据 */ triggerCallbacks(operation, entity, data) { // 触发全局回调 this.callbacks.all.forEach(cb => cb(operation, entity, data)); // 触发特定实体回调 if (this.callbacks[entity]) { this.callbacks[entity].forEach(cb => cb(operation, data)); } } /** * 执行CRUD操作并触发回调 */ async crudOperation(operation, entity, data) { try { const response = await fetch(`${this.baseUrl}/app/${operation}/${entity}`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data) }); if (!response.ok) throw new Error('Network response was not ok'); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || 'API error'); // 触发操作成功的回调 this.triggerCallbacks(operation, entity, data); // 自动同步数据 this.syncData(); return result; } catch (error) { console.error('CRUD error:', error); // 触发操作失败的回调 this.triggerCallbacks(`${operation}_error`, entity, { data, error: error.message }); throw error; } } /** * 执行CRUD操作 * @param {string} operation - 'add', 'delete', 'update' * @param {string} entity - 实体名称(小写) * @param {Object} data - 要发送的数据 * @returns {Promise<Object>} 响应结果 */ async crudOperation(operation, entity, data) { try { const response = await fetch(`${this.baseUrl}/app/${operation}/${entity}`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data) }); if (!response.ok) throw new Error('Network response was not ok'); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || 'API error'); // 触发操作成功的回调 this.triggerCallbacks(operation, entity, data); // 自动同步数据 this.syncData(); return result; } catch (error) { console.error('CRUD error:', error); // 触发操作失败的回调 this.triggerCallbacks(`${operation}_error`, entity, { data, error: error.message }); throw error; } } /** * 自动同步数据(防止频繁请求) */ async syncData() { if (this.isSyncing) return; // 距离上次同步超过5秒才执行新同步 if (this.lastSync && new Date() - this.lastSync < 5000) { setTimeout(() => this.syncData(), 5000 - (new Date() - this.lastSync)); return; } this.isSyncing = true; try { await this.fetchAll(); } finally { this.isSyncing = false; } } /** * 添加实体 * @param {string} entity - 实体名称 * @param {Object} data - 实体数据 */ async addEntity(entity, data) { return this.crudOperation('add', entity, data); } /** * 更新实体 * @param {string} entity - 实体名称 * @param {Object} data - 实体数据(必须包含id) */ async updateEntity(entity, data) { return this.crudOperation('update', entity, data); } /** * 删除实体 * @param {string} entity - 实体名称 * @param {number} id - 实体ID */ async deleteEntity(entity, id) { return this.crudOperation('delete', entity, {id}); } } export { DataManager }; // 创建单例实例 //const dataManager = new DataManager('http://127.0.0.1:8080/KuCun2'); // 初始化时获取所有数据 //dataManager.fetchAll().then(() => { // console.log('Initial data loaded'); //}); // 导出数据对象,外部可以直接访问 data.bancais, data.dingdans 等 export const data = dataManager.data; // 导出操作方法 export const addEntity = dataManager.addEntity.bind(dataManager); export const updateEntity = dataManager.updateEntity.bind(dataManager); export const deleteEntity = dataManager.deleteEntity.bind(dataManager); export const fetchAll = dataManager.fetchAll.bind(dataManager);index.html:35 Failed to initialize DataManager: ReferenceError: DataManager is not defined at HTMLDocument.<anonymous> (index.html:21:32)
最新发布
06-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值