Starts a session with the driver Capabilities of the browser
(ICapabilities capabilities)
| 590 | /// </summary> |
| 591 | /// <param name="capabilities">Capabilities of the browser</param> |
| 592 | [MemberNotNull(nameof(SessionId))] |
| 593 | [MemberNotNull(nameof(Capabilities))] |
| 594 | protected void StartSession(ICapabilities capabilities) |
| 595 | { |
| 596 | Dictionary<string, object?> parameters = new Dictionary<string, object?>(); |
| 597 | |
| 598 | // If the object passed into the RemoteWebDriver constructor is a |
| 599 | // RemoteSessionSettings object, it is expected that all intermediate |
| 600 | // and end nodes are compliant with the W3C WebDriver Specification, |
| 601 | // and therefore will already contain all of the appropriate values |
| 602 | // for establishing a session. |
| 603 | if (capabilities is not RemoteSessionSettings remoteSettings) |
| 604 | { |
| 605 | Dictionary<string, object> matchCapabilities = this.GetCapabilitiesDictionary(capabilities); |
| 606 | |
| 607 | if (this.CommandExecutor is Remote.HttpCommandExecutor httpExecutor) |
| 608 | { |
| 609 | matchCapabilities["se:remoteUrl"] = httpExecutor.RemoteServerUri.AbsoluteUri; |
| 610 | } |
| 611 | |
| 612 | List<object> firstMatchCapabilitiesList = new List<object>(); |
| 613 | firstMatchCapabilitiesList.Add(matchCapabilities); |
| 614 | |
| 615 | Dictionary<string, object> specCompliantCapabilitiesDictionary = new Dictionary<string, object>(); |
| 616 | specCompliantCapabilitiesDictionary["firstMatch"] = firstMatchCapabilitiesList; |
| 617 | |
| 618 | parameters.Add("capabilities", specCompliantCapabilitiesDictionary); |
| 619 | } |
| 620 | else |
| 621 | { |
| 622 | Dictionary<string, object?> remoteSettingsDictionary = remoteSettings.ToDictionary(); |
| 623 | |
| 624 | // Advertise se:remoteUrl on the caller's behalf, as every other binding does. It must be |
| 625 | // nested in alwaysMatch (the Grid drops top-level metadata), built into a fresh copy so |
| 626 | // the caller-owned RemoteSessionSettings is not mutated. Only a matched capability counts |
| 627 | // as explicit here: a se:remoteUrl set via AddMetadataSetting stays top-level, is ignored |
| 628 | // by the Grid, and does not suppress this injection (the executor URL stays authoritative). |
| 629 | // Skip only when se:remoteUrl already lives in alwaysMatch/firstMatch, to preserve that |
| 630 | // value and avoid an alwaysMatch/firstMatch overlap. If only one of several firstMatch |
| 631 | // alternatives sets it explicitly, injection is suppressed for all of them; that |
| 632 | // multi-alternative case is intentionally not supported. |
| 633 | if (this.CommandExecutor is Remote.HttpCommandExecutor remoteHttpExecutor |
| 634 | && !ContainsMatchCapability(remoteSettingsDictionary, "se:remoteUrl")) |
| 635 | { |
| 636 | Dictionary<string, object?> alwaysMatch = new Dictionary<string, object?>(); |
| 637 | if (remoteSettingsDictionary.TryGetValue("alwaysMatch", out object? existingAlwaysMatch) |
| 638 | && existingAlwaysMatch is IDictionary<string, object> existingCapabilities) |
| 639 | { |
| 640 | foreach (KeyValuePair<string, object> capability in existingCapabilities) |
| 641 | { |
| 642 | alwaysMatch[capability.Key] = capability.Value; |
| 643 | } |
| 644 | } |
| 645 | |
| 646 | alwaysMatch["se:remoteUrl"] = remoteHttpExecutor.RemoteServerUri.AbsoluteUri; |
| 647 | remoteSettingsDictionary["alwaysMatch"] = alwaysMatch; |
| 648 | } |
| 649 |
no test coverage detected