Fix crash in chromedriver
This fixes a chromedriver crash when a click command closes the
browser.
This fix is similar to
https://chromium-review.googlesource.com/c/chromium/src/+/3891125
kTargetDetached needs to be handled since
https://chromium-review.googlesource.com/c/chromium/src/+/5565103
Bug: 42323264
Change-Id: I145d52b1f55cecfa044527fb87c65d4791b0ef2f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5934524
Auto-Submit: Tomasz Moniuszko <tmoniuszko@opera.com>
Commit-Queue: Maksim Sadym <sadym@chromium.org>
Reviewed-by: Vladimir Nechaev <nechaev@chromium.org>
Reviewed-by: Maksim Sadym <sadym@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1373261}
diff --git a/chrome/test/chromedriver/commands.cc b/chrome/test/chromedriver/commands.cc
index 9f93fc3a..ca436c2 100644
--- a/chrome/test/chromedriver/commands.cc
+++ b/chrome/test/chromedriver/commands.cc
@@ -327,10 +327,24 @@
", but failed to kill browser:" + quit_status.message();
}
status = Status(kUnknownError, message, status);
- } else if (status.code() == kDisconnected ||
- status.code() == kTargetDetached) {
+ } else if (status.code() == kDisconnected) {
+ session->quit = true;
+ std::string message(
+ "session deleted as the browser has closed the connection");
+ if (!session->detach) {
+ // Even though the connection was lost that makes the graceful
+ // shutdown impossible the Quit procedure falls back on killing the
+ // process in case if it is still alive.
+ Status quit_status = session->chrome->Quit();
+ if (quit_status.IsError()) {
+ message +=
+ ", but failed to kill browser:" + quit_status.message();
+ }
+ }
+ status = Status(kInvalidSessionId, message, status);
+ } else if (status.code() == kTargetDetached) {
// Some commands, like clicking a button or link which closes the
- // window, may result in a kDisconnected error code.
+ // window, may result in a kTargetDetached error code.
std::list<std::string> web_view_ids;
Status status_tmp = session->chrome->GetWebViewIds(
&web_view_ids, session->w3c_compliant);
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index 6b2b4ca0..7e5a6f8 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -4170,15 +4170,27 @@
self.WaitForCondition(
lambda: len(self._driver.GetWindowHandles()) == 1))
+ def _sessionIsOver(self):
+ try:
+ self._driver.GetWindowHandles()
+ return False
+ except chromedriver.InvalidSessionId:
+ return True
+
def testCloseLastWindow(self):
- def sessionIsOver():
- try:
- self._driver.GetWindowHandles()
- return False
- except chromedriver.InvalidSessionId:
- return True
- self._driver.CloseWindow()
- self.WaitForCondition(sessionIsOver)
+ self._driver.CloseWindow()
+ self.WaitForCondition(self._sessionIsOver)
+
+ def testDoesntCrashOnClosingBrowserFromAsyncScript(self):
+ # Regression test for https://crbug.com/42323264.
+ old_handles = self._driver.GetWindowHandles()
+ self._driver.ExecuteScript('window.open()')
+ new_window = self.WaitForNewWindow(self._driver, old_handles)
+ self._driver.CloseWindow()
+ self._driver.SwitchToWindow(new_window)
+ self._driver.ExecuteAsyncScript(
+ 'done=arguments[0]; setTimeout(() => {done();}, 1); window.close()')
+ self.WaitForCondition(self._sessionIsOver)
class ChromeDriverBackgroundTest(ChromeDriverBaseTestWithWebServer):
def setUp(self):
diff --git a/chrome/test/chromedriver/window_commands.cc b/chrome/test/chromedriver/window_commands.cc
index 9df57e1..b79008c 100644
--- a/chrome/test/chromedriver/window_commands.cc
+++ b/chrome/test/chromedriver/window_commands.cc
@@ -735,10 +735,11 @@
// When pageload strategy is None, new navigation can occur during
// execution of a command. Retry the command.
continue;
- } else if (status.code() == kDisconnected) {
+ } else if (status.code() == kDisconnected ||
+ status.code() == kTargetDetached) {
// Some commands, like clicking a button or link which closes the window,
- // may result in a kDisconnected error code. |web_view| may be invalid at
- // at this point.
+ // may result in a kDisconnected or kTargetDetached error code.
+ // |web_view| may be invalid at this point.
return status;
} else if (status.IsError()) {
// If the command failed while a new page or frame started loading, retry