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