summaryrefslogtreecommitdiffstats
path: root/webkit/default_plugin/plugin_install_job_monitor.cc
blob: 5851beeb6c13336fddabe52ccb9214b23ccd3572 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Copyright (c) 2006-2008 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 "webkit/default_plugin/plugin_install_job_monitor.h"

#include "webkit/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) {
        DLOG(INFO) << "All processes in the installer job have exited.";
        DLOG(INFO) << "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;
}