blob: 4e1905751e036297cef1d78c17e7b1571650541a [file] [log] [blame]
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/default_plugin/plugin_install_job_monitor.h"
#include "base/message_loop.h"
#include "chrome/default_plugin/plugin_impl.h"
PluginInstallationJobMonitorThread::PluginInstallationJobMonitorThread()
: Thread("Chrome plugin install thread"),
install_job_completion_port_(NULL),
stop_job_monitoring_(false),
plugin_window_(NULL),
install_job_(NULL) {
}
PluginInstallationJobMonitorThread::~PluginInstallationJobMonitorThread() {
if (install_job_) {
::CloseHandle(install_job_);
install_job_ = NULL;
}
}
bool PluginInstallationJobMonitorThread::Initialize() {
DCHECK(install_job_ == NULL);
install_job_ = ::CreateJobObject(NULL, NULL);
if (install_job_ == NULL) {
DLOG(ERROR) << "Failed to create plugin install job. Error = "
<< ::GetLastError();
NOTREACHED();
return false;
}
return Start();
}
void PluginInstallationJobMonitorThread::Init() {
this->message_loop()->PostTask(FROM_HERE,
NewRunnableMethod(this,
&PluginInstallationJobMonitorThread::WaitForJobThread));
}
void PluginInstallationJobMonitorThread::WaitForJobThread() {
if (!install_job_) {
DLOG(WARNING) << "Invalid job information";
NOTREACHED();
return;
}
DCHECK(install_job_completion_port_ == NULL);
install_job_completion_port_ =
::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL,
reinterpret_cast<ULONG_PTR>(install_job_), 0);
DCHECK(install_job_completion_port_ != NULL);
JOBOBJECT_ASSOCIATE_COMPLETION_PORT job_completion_port = {0};
job_completion_port.CompletionKey = install_job_;
job_completion_port.CompletionPort = install_job_completion_port_;
if (!SetInformationJobObject(install_job_,
JobObjectAssociateCompletionPortInformation,
&job_completion_port,
sizeof(job_completion_port))) {
DLOG(WARNING) << "Failed to associate completion port with job object.Err "
<< ::GetLastError();
NOTREACHED();
return;
}
while (!stop_job_monitoring_) {
unsigned long job_event = 0;
unsigned long completion_key = 0;
LPOVERLAPPED overlapped = NULL;
if (::GetQueuedCompletionStatus(
install_job_completion_port_, &job_event,
&completion_key, &overlapped, INFINITE)) {
if (job_event == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) {
DVLOG(1) << "All processes in the installer job have exited. "
"Initiating refresh on the plugins list";
DCHECK(::IsWindow(plugin_window_));
PostMessageW(plugin_window_,
PluginInstallerImpl::kRefreshPluginsMessage, 0, 0);
}
}
}
}
void PluginInstallationJobMonitorThread::Stop() {
stop_job_monitoring_ = true;
::PostQueuedCompletionStatus(
install_job_completion_port_, JOB_OBJECT_MSG_END_OF_JOB_TIME,
reinterpret_cast<ULONG_PTR>(install_job_), NULL);
Thread::Stop();
::CloseHandle(install_job_completion_port_);
install_job_completion_port_ = NULL;
}
bool PluginInstallationJobMonitorThread::AssignProcessToJob(
HANDLE process_handle) {
BOOL result = AssignProcessToJobObject(install_job_, process_handle);
return result ? true : false;
}