3939 *       Then the {@code stereotype} must contain the same values. 
4040 * </ul> 
4141 * 
42-  * <p>One thing to note is that extension capabilities are not considered when matching slots, since 
43-  * the matching of these is implementation-specific to each driver. 
42+  * <p>Note that extension capabilities are considered for slot matching, with the following exceptions: 
43+  * 
44+  * <ul> 
45+  *   <li>Extension capabilities with prefix "se:" 
46+  *   <li>Extension capabilities with these suffixes: 
47+  *     <ul> 
48+  *       <li>"options" 
49+  *       <li>"Options" 
50+  *       <li>"loggingPrefs" 
51+  *       <li>"debuggerAddress" 
52+  *     </ul> 
53+  * </ul> 
4454 */ 
4555public  class  DefaultSlotMatcher  implements  SlotMatcher , Serializable  {
4656
4757  /* 
48-    List of prefixed  extension capabilities  we never should try to match, they should be 
58+    List of extension capability suffixes  we never should try to match, they should be 
4959   matched in the Node or in the browser driver. 
5060  */ 
51-   private  static  final  List <String > EXTENSION_CAPABILITIES_PREFIXES  =
52-       Arrays .asList ("goog: " , "moz: " , "ms: " , "se: " );
61+   private  static  final  List <String > EXTENSION_CAPABILITY_SUFFIXES  =
62+       Arrays .asList ("Options " , "options " , "loggingPrefs " , "debuggerAddress " );
5363
5464  @ Override 
5565  public  boolean  matches (Capabilities  stereotype , Capabilities  capabilities ) {
@@ -76,14 +86,14 @@ public boolean matches(Capabilities stereotype, Capabilities capabilities) {
7686
7787    // At the end, a simple browser, browserVersion and platformName match 
7888    boolean  browserNameMatch  =
79-         (capabilities .getBrowserName () == null  || capabilities .getBrowserName ().isEmpty ())
89+         capabilities .getBrowserName () == null 
90+             || capabilities .getBrowserName ().isEmpty ()
8091            || Objects .equals (stereotype .getBrowserName (), capabilities .getBrowserName ());
8192    boolean  browserVersionMatch  =
82-         (capabilities .getBrowserVersion () == null 
83-                 || capabilities .getBrowserVersion ().isEmpty ()
84-                 || Objects .equals (capabilities .getBrowserVersion (), "stable" ))
85-             || browserVersionMatch (
86-                 stereotype .getBrowserVersion (), capabilities .getBrowserVersion ());
93+         capabilities .getBrowserVersion () == null 
94+             || capabilities .getBrowserVersion ().isEmpty ()
95+             || Objects .equals (capabilities .getBrowserVersion (), "stable" )
96+             || browserVersionMatch (stereotype .getBrowserVersion (), capabilities .getBrowserVersion ());
8797    boolean  platformNameMatch  =
8898        capabilities .getPlatformName () == null 
8999            || Objects .equals (stereotype .getPlatformName (), capabilities .getPlatformName ())
@@ -102,21 +112,17 @@ private Boolean initialMatch(Capabilities stereotype, Capabilities capabilities)
102112        .filter (name  -> !name .contains (":" ))
103113        // Platform matching is special, we do it later 
104114        .filter (name  -> !"platformName" .equalsIgnoreCase (name ))
105-         .map (
115+         .filter (name  -> capabilities .getCapability (name ) != null )
116+         .allMatch (
106117            name  -> {
107-               if  (capabilities .getCapability (name ) instanceof  String ) {
108-                 return  stereotype 
109-                     .getCapability (name )
110-                     .toString ()
111-                     .equalsIgnoreCase (capabilities .getCapability (name ).toString ());
112-               } else  {
113-                 return  capabilities .getCapability (name ) == null 
114-                     || Objects .equals (
115-                         stereotype .getCapability (name ), capabilities .getCapability (name ));
118+               if  (stereotype .getCapability (name ) instanceof  String 
119+                   && capabilities .getCapability (name ) instanceof  String ) {
120+                 return  ((String ) stereotype .getCapability (name ))
121+                     .equalsIgnoreCase ((String ) capabilities .getCapability (name ));
116122              }
117-             }) 
118-         . reduce ( Boolean :: logicalAnd ) 
119-         . orElse ( true );
123+                return   Objects . equals ( 
124+                    stereotype . getCapability ( name ),  capabilities . getCapability ( name )); 
125+             } );
120126  }
121127
122128  private  Boolean  managedDownloadsEnabled (Capabilities  stereotype , Capabilities  capabilities ) {
@@ -140,39 +146,39 @@ private Boolean platformVersionMatch(Capabilities stereotype, Capabilities capab
140146    */ 
141147    return  capabilities .getCapabilityNames ().stream ()
142148        .filter (name  -> name .contains ("platformVersion" ))
143-         .map (
149+         .allMatch (
144150            platformVersionCapName  ->
145151                Objects .equals (
146152                    stereotype .getCapability (platformVersionCapName ),
147-                     capabilities .getCapability (platformVersionCapName )))
148-         .reduce (Boolean ::logicalAnd )
149-         .orElse (true );
153+                     capabilities .getCapability (platformVersionCapName )));
150154  }
151155
152156  private  Boolean  extensionCapabilitiesMatch (Capabilities  stereotype , Capabilities  capabilities ) {
153157    /* 
154-      We match extension capabilities when they are not prefixed with any of  the 
155-      EXTENSION_CAPABILITIES_PREFIXES items. Also, we match them only when the capabilities  
156-      of  the new session request contains that specific extension capability . 
158+      We match extension capabilities in new session requests whose names do not have  the prefix "se:" or  
159+      one of the reserved suffixes ("options", "Options", "loggingPrefs", or "debuggerAddress"). These are  
160+      forwarded to  the matched node for use in configuration, but are not considered for node matching . 
157161    */ 
158162    return  stereotype .getCapabilityNames ().stream ()
163+         // examine only extension capabilities 
159164        .filter (name  -> name .contains (":" ))
160-         .filter (name  -> capabilities .asMap ().containsKey (name ))
161-         .filter (name  -> EXTENSION_CAPABILITIES_PREFIXES .stream ().noneMatch (name ::contains ))
162-         .map (
165+         // ignore Selenium extension capabilities 
166+         .filter (name  -> !name .startsWith ("se:" ))
167+         // ignore special extension capability suffixes 
168+         .filter (name  -> EXTENSION_CAPABILITY_SUFFIXES .stream ().noneMatch (name ::endsWith ))
169+         // ignore capabilities not specified in the request 
170+         .filter (name  -> capabilities .getCapability (name ) != null )
171+         .allMatch (
163172            name  -> {
164-               if  (capabilities .getCapability (name ) instanceof  String ) {
165-                 return  stereotype 
166-                     .getCapability (name )
167-                     .toString ()
168-                     .equalsIgnoreCase (capabilities .getCapability (name ).toString ());
169-               } else  {
170-                 return  capabilities .getCapability (name ) == null 
171-                     || Objects .equals (
172-                         stereotype .getCapability (name ), capabilities .getCapability (name ));
173+               // evaluate capabilities with String values 
174+               if  (stereotype .getCapability (name ) instanceof  String 
175+                   && capabilities .getCapability (name ) instanceof  String ) {
176+                 return  ((String ) stereotype .getCapability (name ))
177+                     .equalsIgnoreCase ((String ) capabilities .getCapability (name ));
173178              }
174-             })
175-         .reduce (Boolean ::logicalAnd )
176-         .orElse (true );
179+               // evaluate capabilities with Number or Boolean values 
180+               return  Objects .equals (
181+                   stereotype .getCapability (name ), capabilities .getCapability (name ));
182+             });
177183  }
178184}
0 commit comments