// 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(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(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; }