Home | History | Annotate | Download | only in mini_installer
      1 # Copyright 2013 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """Common helper module for working with Chrome's processes and windows."""
      6 
      7 import ctypes
      8 import pywintypes
      9 import re
     10 import win32con
     11 import win32gui
     12 import win32process
     13 
     14 
     15 def GetProcessIDAndPathPairs():
     16   """Returns a list of 2-tuples of (process id, process path).
     17 
     18   This is needed because psutil is not available on Windows slave machines (see:
     19   http://crbug.com/257696).
     20   TODO(sukolsak): Use psutil.process_iter() once it becomes available.
     21   """
     22   process_id_and_path_pairs = []
     23   for process_id in win32process.EnumProcesses():
     24     process_handle = ctypes.windll.kernel32.OpenProcess(
     25         win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, False,
     26         process_id)
     27     if not process_handle:
     28       continue
     29     try:
     30       process_path = win32process.GetModuleFileNameEx(process_handle, 0)
     31       process_id_and_path_pairs.append((process_id, process_path))
     32     except pywintypes.error:
     33       # It's normal that some processes are not accessible.
     34       pass
     35   return process_id_and_path_pairs
     36 
     37 
     38 def GetProcessIDs(process_path):
     39   """Returns a list of IDs of processes whose path is |process_path|.
     40 
     41   Args:
     42     process_path: The path to the process.
     43 
     44   Returns:
     45     A list of process IDs.
     46   """
     47   return [pid for (pid, path) in GetProcessIDAndPathPairs() if
     48           path == process_path]
     49 
     50 
     51 def GetWindowHandles(process_ids):
     52   """Returns a list of handles of windows owned by processes in |process_ids|.
     53 
     54   Args:
     55     process_ids: A list of process IDs.
     56 
     57   Returns:
     58     A list of handles of windows owned by processes in |process_ids|.
     59   """
     60   hwnds = []
     61   def EnumerateWindowCallback(hwnd, _):
     62     _, found_process_id = win32process.GetWindowThreadProcessId(hwnd)
     63     if found_process_id in process_ids and win32gui.IsWindowVisible(hwnd):
     64       hwnds.append(hwnd)
     65   # Enumerate all the top-level windows and call the callback with the hwnd as
     66   # the first parameter.
     67   win32gui.EnumWindows(EnumerateWindowCallback, None)
     68   return hwnds
     69 
     70 
     71 def WindowExists(process_ids, class_pattern):
     72   """Returns whether there exists a window with the specified criteria.
     73 
     74   This method returns whether there exists a window that is owned by a process
     75   in |process_ids| and has a class name that matches |class_pattern|.
     76 
     77   Args:
     78     process_ids: A list of process IDs.
     79     class_pattern: The regular expression pattern of the window class name.
     80 
     81   Returns:
     82     A boolean indicating whether such window exists.
     83   """
     84   for hwnd in GetWindowHandles(process_ids):
     85     if re.match(class_pattern, win32gui.GetClassName(hwnd)):
     86       return True
     87   return False
     88