webui的資源被編譯在chrome.dll下,當在地址欄里輸入一個內部url時,它所對應的資源會從chrome.dll找到。每當修改前端代碼之后都要再編譯一次chrome.dll,這很浪費時間,而且前端一般由非C++程序員負責,要讓他們去編譯,實在不合理,所以必須有辦法可以重定向url到本地文件。通過咨詢、查看代碼,找到了解決方法。
webui,以“chrome”為前綴的url跟“UI處理對象”的關聯是在“src\chrome\browser\ui\webui\chrome_web_ui_controller_factory.cc”里做的。UI處理對象負責定位到對應的前端頁面、以及處理導出js接口跟C++邏輯的綁定。所以要重定向前端頁面的路徑必須在UI處理對象中做。
以前幾天寫的HelloWorldUI為例。前端資源的獲取源自HelloWorldUI類的構造函數。
ChromeWebUIDataSource* html_source = new ChromeWebUIDataSource(chrome::kChromeUIHelloWorldHost);
ChromeWebUIDataSource可以被派生,如果要重定位Chrome://Hello-world資源所在位置,派生后,重寫StartDataRequest函數實現即可。所以重點是StartDataRequest函數。在該函數里把新路徑(D:\chromium_resources_test)下的文件內容讀取出來,接到原來的邏輯上即可,如果新路徑不存在,則還是使用原來的前端資源。
virtual void StartDataRequest(const std::string& path, bool is_incognito, int request_id) { FilePath web_file_path(L"D:\\chromium_resources_test\\"); web_file_path = web_file_path.AppendASCII(source_name()); //以hostname作為文件夾名 web_file_path = web_file_path.AppendASCII(path); file_util::MemoryMappedFile memmap_file; bool bFile = memmap_file.Initialize(web_file_path); if (bFile) { scoped_refptr<base::RefCountedString> response = new base::RefCountedString(); response->data() = reinterpret_cast<const char*>(memmap_file.data()); SendResponse(request_id, response); } ChromeWebUIDataSource::StartDataRequest(path, is_incognito, request_id); }
這樣子就可以把資源文件放在D:\chromium_resources_test中,譬如這個helloworld的資源就可以存放在D:\chromium_resources_test\hello-world\ 路徑下。
工欲善其事,必先利其器。
詳細例子代碼參見附件:http://files.cnblogs.com/cswuyg/redirect_webui_resource.zip