Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / test / mini_installer / quit_chrome.py
blobc25d8da4d27e62772159f4adb4362a85ed1032f6
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.
5 """Quits Chrome.
7 This script sends a WM_CLOSE message to each window of Chrome and waits until
8 the process terminates.
9 """
11 import optparse
12 import os
13 import pywintypes
14 import sys
15 import time
16 import win32con
17 import win32gui
18 import winerror
20 import chrome_helper
23 def CloseWindows(process_path):
24 """Closes all windows owned by processes whose exe path is |process_path|.
26 Args:
27 process_path: The path to the executable whose processes will have their
28 windows closed.
30 Returns:
31 A boolean indicating whether the processes successfully terminated within
32 25 seconds.
33 """
34 start_time = time.time()
35 while time.time() - start_time < 25:
36 process_ids = chrome_helper.GetProcessIDs(process_path)
37 if not process_ids:
38 return True
40 for hwnd in chrome_helper.GetWindowHandles(process_ids):
41 try:
42 win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0)
43 except pywintypes.error as error:
44 # It's normal that some window handles have become invalid.
45 if error.args[0] != winerror.ERROR_INVALID_WINDOW_HANDLE:
46 raise
47 time.sleep(0.1)
48 return False
51 def KillNamedProcess(process_path):
52 """ Kills all running exes with the same name as the exe at |process_path|.
54 Args:
55 process_path: The path to an executable.
57 Returns:
58 True if running executables were successfully killed. False otherwise.
59 """
60 return os.system('taskkill /f /im %s' % os.path.basename(process_path)) == 0
63 def QuitChrome(chrome_path):
64 """ Tries to quit chrome in a safe way. If there is still an open instance
65 after a timeout delay, the process is killed the hard way.
67 Args:
68 chrome_path: The path to chrome.exe.
69 """
70 if not CloseWindows(chrome_path):
71 # TODO(robertshield): Investigate why Chrome occasionally doesn't shut down.
72 sys.stderr.write('Warning: Chrome not responding to window closure. '
73 'Killing all processes belonging to %s\n' % chrome_path)
74 KillNamedProcess(chrome_path)
77 def main():
78 usage = 'usage: %prog chrome_path'
79 parser = optparse.OptionParser(usage, description='Quit Chrome.')
80 _, args = parser.parse_args()
81 if len(args) != 1:
82 parser.error('Incorrect number of arguments.')
83 chrome_path = args[0]
85 QuitChrome(chrome_path)
86 return 0
89 if __name__ == '__main__':
90 sys.exit(main())