From 702b1c7c99b053e235e19ae6cb555c2e1bd76c9e Mon Sep 17 00:00:00 2001 From: Jim Evans Date: Wed, 22 Sep 2021 17:48:45 -0400 Subject: [PATCH] [dotnet] Rename TerminateDevToolsSession to ResetDevToolsSession For the case where a CDP session is made invalid, for example, because a window is closed, this method will now reset the CDP session so that the user can continue to use it without closing and establishing a new web socket connection. Also added disposal of DevTools sessions to Firefox and Remote when required. --- .../src/webdriver/Chromium/ChromiumDriver.cs | 9 ++- .../src/webdriver/DevTools/DevToolsSession.cs | 75 +++++++++++-------- dotnet/src/webdriver/DevTools/IDevTools.cs | 5 +- dotnet/src/webdriver/Firefox/FirefoxDriver.cs | 22 +++++- .../src/webdriver/Remote/RemoteWebDriver.cs | 22 +++++- 5 files changed, 91 insertions(+), 42 deletions(-) diff --git a/dotnet/src/webdriver/Chromium/ChromiumDriver.cs b/dotnet/src/webdriver/Chromium/ChromiumDriver.cs index 097612e6a76d8..6c26d1ccc35ba 100644 --- a/dotnet/src/webdriver/Chromium/ChromiumDriver.cs +++ b/dotnet/src/webdriver/Chromium/ChromiumDriver.cs @@ -216,12 +216,15 @@ public DevToolsSession GetDevToolsSession(int devToolsProtocolVersion) return this.devToolsSession; } - public void TerminateDevToolsSession() + /// + /// Resets a DevTools session + /// + public void ResetDevToolsSession() { if (this.devToolsSession != null) { - this.devToolsSession.Dispose(); - this.devToolsSession = null; + this.devToolsSession.ActiveSessionId = null; + this.devToolsSession.InitializeSession().ConfigureAwait(false).GetAwaiter().GetResult(); } } diff --git a/dotnet/src/webdriver/DevTools/DevToolsSession.cs b/dotnet/src/webdriver/DevTools/DevToolsSession.cs index fa6905429a569..2903bdc551b53 100644 --- a/dotnet/src/webdriver/DevTools/DevToolsSession.cs +++ b/dotnet/src/webdriver/DevTools/DevToolsSession.cs @@ -249,10 +249,49 @@ public T GetVersionSpecificDomains() where T: DevToolsSessionDomains /// /// Asynchronously starts the session. /// - /// The version of the protocol to use in communicating with the browswer. + /// The requested version of the protocol to use in communicating with the browswer. /// A task that represents the asynchronous operation. - internal async Task Start(int protocolVersion) + internal async Task Start(int requestedProtocolVersion) { + int protocolVersion = await InitializeProtocol(requestedProtocolVersion); + this.domains = DevToolsDomains.InitializeDomains(protocolVersion, this); + await this.InitializeSession(); + } + + internal async Task InitializeSession() + { + string targetId = null; + var targets = await this.domains.Target.GetTargets(); + foreach (var target in targets) + { + if (target.Type == "page") + { + targetId = target.TargetId; + LogTrace("Found Target ID {0}.", targetId); + string sessionId = await this.domains.Target.AttachToTarget(targetId); + LogTrace("Target ID {0} attached. Active session ID: {1}", targetId, sessionId); + this.ActiveSessionId = sessionId; + break; + } + } + + await this.domains.Target.SetAutoAttach(); + LogTrace("AutoAttach is set.", targetId); + try + { + // Wrap this in a try-catch, because it's not the end of the + // world if clearing the log doesn't work. + await this.domains.Log.Clear(); + LogTrace("Log cleared.", targetId); + } + catch (WebDriverException) + { + } + } + + private async Task InitializeProtocol(int requestedProtocolVersion) + { + int protocolVersion = requestedProtocolVersion; if (this.websocketAddress == null) { string debuggerUrl = string.Format(CultureInfo.InvariantCulture, "http://{0}", this.debuggerEndpoint); @@ -266,7 +305,7 @@ internal async Task Start(int protocolVersion) var versionInfo = JsonConvert.DeserializeObject(rawVersionInfo); this.websocketAddress = versionInfo.WebSocketDebuggerUrl; - if (protocolVersion == AutoDetectDevToolsProtocolVersion) + if (requestedProtocolVersion == AutoDetectDevToolsProtocolVersion) { bool versionParsed = int.TryParse(versionInfo.BrowserMajorVersion, out protocolVersion); if (!versionParsed) @@ -283,35 +322,7 @@ internal async Task Start(int protocolVersion) } } - this.domains = DevToolsDomains.InitializeDomains(protocolVersion, this); - - string targetId = null; - var targets = await this.domains.Target.GetTargets(); - foreach(var target in targets) - { - if (target.Type == "page") - { - targetId = target.TargetId; - LogTrace("Found Target ID {0}.", targetId); - string sessionId = await this.domains.Target.AttachToTarget(targetId); - LogTrace("Target ID {0} attached. Active session ID: {1}", targetId, sessionId); - this.ActiveSessionId = sessionId; - break; - } - } - - await this.domains.Target.SetAutoAttach(); - LogTrace("AutoAttach is set.", targetId); - try - { - // Wrap this in a try-catch, because it's not the end of the - // world if clearing the log doesn't work. - await this.domains.Log.Clear(); - LogTrace("Log cleared.", targetId); - } - catch (WebDriverException) - { - } + return protocolVersion; } private async Task OpenSessionConnection(CancellationToken cancellationToken) diff --git a/dotnet/src/webdriver/DevTools/IDevTools.cs b/dotnet/src/webdriver/DevTools/IDevTools.cs index 4a9e66cdcd172..c108a2b9001ae 100644 --- a/dotnet/src/webdriver/DevTools/IDevTools.cs +++ b/dotnet/src/webdriver/DevTools/IDevTools.cs @@ -36,6 +36,9 @@ public interface IDevTools /// The active session to use to communicate with the Developer Tools debugging protocol. DevToolsSession GetDevToolsSession(int protocolVersion); - void TerminateDevToolsSession(); + /// + /// Resets a DevTools session + /// + void ResetDevToolsSession(); } } diff --git a/dotnet/src/webdriver/Firefox/FirefoxDriver.cs b/dotnet/src/webdriver/Firefox/FirefoxDriver.cs index acf7579725171..287222b11a976 100644 --- a/dotnet/src/webdriver/Firefox/FirefoxDriver.cs +++ b/dotnet/src/webdriver/Firefox/FirefoxDriver.cs @@ -300,12 +300,15 @@ public DevToolsSession GetDevToolsSession(int devToolsProtocolVersion) return this.devToolsSession; } - public void TerminateDevToolsSession() + /// + /// Resets a DevTools session + /// + public void ResetDevToolsSession() { if (this.devToolsSession != null) { - this.devToolsSession.Dispose(); - this.devToolsSession = null; + this.devToolsSession.ActiveSessionId = null; + this.devToolsSession.InitializeSession().ConfigureAwait(false).GetAwaiter().GetResult(); } } @@ -317,6 +320,19 @@ protected virtual void PrepareEnvironment() // Does nothing, but provides a hook for subclasses to do "stuff" } + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (this.devToolsSession != null) + { + this.devToolsSession.Dispose(); + } + } + + base.Dispose(disposing); + } + private static ICapabilities ConvertOptionsToCapabilities(FirefoxOptions options) { if (options == null) diff --git a/dotnet/src/webdriver/Remote/RemoteWebDriver.cs b/dotnet/src/webdriver/Remote/RemoteWebDriver.cs index 8dd0e18195f23..7408fcedc35db 100644 --- a/dotnet/src/webdriver/Remote/RemoteWebDriver.cs +++ b/dotnet/src/webdriver/Remote/RemoteWebDriver.cs @@ -444,13 +444,29 @@ public DevToolsSession GetDevToolsSession(int protocolVersion) return this.devToolsSession; } - public void TerminateDevToolsSession() + /// + /// Resets a DevTools session + /// + public void ResetDevToolsSession() { if (this.devToolsSession != null) { - this.devToolsSession.Dispose(); - this.devToolsSession = null; + this.devToolsSession.ActiveSessionId = null; + this.devToolsSession.InitializeSession().ConfigureAwait(false).GetAwaiter().GetResult(); + } + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (this.devToolsSession != null) + { + this.devToolsSession.Dispose(); + } } + + base.Dispose(disposing); } private static ICapabilities ConvertOptionsToCapabilities(DriverOptions options)