web-ui和js交互,为了避免阻塞web-ui的消息循环,不能直接PostTask或直接bind来干活,需要用和UI相关的BrowserThread::PostTask.
通过实验可知,即使用BrowserThread::PostTask,发起的任务很频繁时,web-ui也卡的很。
查了chromium工程中的已有实现,看看BrowserThread都怎么用。发现人家都是用BrowserThread::PostDelayedTask,我也用BrowserThread::PostDelayedTask来发起任务,在任务指定的本类属回调中,再用BrowserThread::PostDelayedTask发起下一个任务。这时,web-ui很流畅,一点都不卡。
BrowserThread::PostDelayedTask的用法例子
web-ui中代码很少,只有初始化的代码。
干活都时绑定一个WebUIMessageHandler子类来干活。
// Class acting as a controller of the chrome://download-internals WebUI.
class DownloadInternalsUIMessageHandler : public content::WebUIMessageHandler,
public download::Logger::Observer {
public:
DownloadInternalsUIMessageHandler();
~DownloadInternalsUIMessageHandler() override;
// content::WebUIMessageHandler implementation.
void RegisterMessages() override;
在WebUIMessageHandler子类中,找一个只有初始化时才执行的成员函数,PostDelayedTask即可。PostDelayedTask非常适合在消息循环中绑定自己类的成员函数来干活。
void DownloadInternalsUIMessageHandler::HandleGetServiceStatus(
const base::ListValue* args) {
AllowJavascript();
const base::Value* callback_id;
CHECK(args->Get(0, &callback_id));
ResolveJavascriptCallback(*callback_id,
download_service_->GetLogger()->GetServiceStatus());
// 这里是服务下载有效, 启动一次本web-ui, 这里只进入一次,很适合自动启动任务
post_ui_task_for_download();
}
void DownloadInternalsUIMessageHandler::post_ui_task_for_download()
{
// http://192.168.2.222/a.txt // 可以用http下载的测试文件
m_str_url_by_js_first = "http://192.168.2.222/a.txt";
BrowserThread::PostDelayedTask(
BrowserThread::UI,
FROM_HERE,
base::BindOnce(&DownloadInternalsUIMessageHandler::HandleStartDownload_url_again, base::Unretained(this)),
base::TimeDelta::FromSeconds(2)); // 延时是以秒为单位的, 都是约数设置10秒延时,有时7秒发起任务,有时11秒发起任务
}
void DownloadInternalsUIMessageHandler::HandleStartDownload_url_again()
{
if (!m_str_url_by_js_first.empty()) {
GURL url_now = GURL(m_str_url_by_js_first);
HandleStartDownload_url(url_now);
}
}
void DownloadInternalsUIMessageHandler::HandleStartDownload_url(GURL& url)
{
if (!url.is_valid()) {
LOG(WARNING) << "Can't parse download URL, try to enter a valid URL.";
return;
}
download::DownloadParams params;
params.guid = base::GenerateGUID();
params.client = download::DownloadClient::DEBUGGING;
params.request_params.method = "GET";
params.request_params.url = url;
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("download_internals_webui_source", R"(
semantics {
sender: "Download Internals Page"
description:
"Starts a download with background download service in WebUI."
trigger:
"User clicks on the download button in "
"chrome://download-internals."
data: "None"
destination: WEBSITE
}
policy {
cookies_allowed: YES
cookies_store: "user"
setting: "This feature cannot be disabled by settings."
policy_exception_justification: "Not implemented."
})");
params.traffic_annotation =
net::MutableNetworkTrafficAnnotationTag(traffic_annotation);
DCHECK(download_service_);
download_service_->StartDownload(params);
}