# Copyright 2013 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. """Common helper module for working with Chrome's processes and windows.""" import ctypes import pywintypes import re import win32con import win32gui import win32process def GetProcessIDAndPathPairs(): """Returns a list of 2-tuples of (process id, process path). This is needed because psutil is not available on Windows slave machines (see: http://crbug.com/257696). TODO(sukolsak): Use psutil.process_iter() once it becomes available. """ process_id_and_path_pairs = [] for process_id in win32process.EnumProcesses(): process_handle = ctypes.windll.kernel32.OpenProcess( win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, False, process_id) if not process_handle: continue try: process_path = win32process.GetModuleFileNameEx(process_handle, 0) process_id_and_path_pairs.append((process_id, process_path)) except pywintypes.error: # It's normal that some processes are not accessible. pass return process_id_and_path_pairs def GetProcessIDs(process_path): """Returns a list of IDs of processes whose path is |process_path|. Args: process_path: The path to the process. Returns: A list of process IDs. """ return [pid for (pid, path) in GetProcessIDAndPathPairs() if path == process_path] def GetWindowHandles(process_ids): """Returns a list of handles of windows owned by processes in |process_ids|. Args: process_ids: A list of process IDs. Returns: A list of handles of windows owned by processes in |process_ids|. """ hwnds = [] def EnumerateWindowCallback(hwnd, _): _, found_process_id = win32process.GetWindowThreadProcessId(hwnd) if found_process_id in process_ids and win32gui.IsWindowVisible(hwnd): hwnds.append(hwnd) # Enumerate all the top-level windows and call the callback with the hwnd as # the first parameter. win32gui.EnumWindows(EnumerateWindowCallback, None) return hwnds def WindowExists(process_ids, class_pattern): """Returns whether there exists a window with the specified criteria. This method returns whether there exists a window that is owned by a process in |process_ids| and has a class name that matches |class_pattern|. Args: process_ids: A list of process IDs. class_pattern: The regular expression pattern of the window class name. Returns: A boolean indicating whether such window exists. """ for hwnd in GetWindowHandles(process_ids): if re.match(class_pattern, win32gui.GetClassName(hwnd)): return True return False