Skip to content

Commit e0e8f01

Browse files
committed
Extract some of the logic for handling new session responses
In a desperate bid to make things a little easier to understand.
1 parent ccfd456 commit e0e8f01

12 files changed

+843
-93
lines changed

java/client/src/org/openqa/selenium/remote/BUCK

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,13 @@ java_library(name = 'remote-lib',
7272
'ErrorHandler.java',
7373
'ExecuteMethod.java',
7474
'FileDetector.java',
75+
'Gecko013ProtocolResponse.java',
76+
'HandshakeResponse.java',
7577
'HttpCommandExecutor.java',
78+
'InitialHandshakeResponse.java',
7679
'JsonException.java',
7780
'JsonToBeanConverter.java',
81+
'JsonWireProtocolResponse.java',
7882
'LocalFileDetector.java',
7983
'ProtocolHandshake.java',
8084
'RemoteExecuteMethod.java',
@@ -90,6 +94,7 @@ java_library(name = 'remote-lib',
9094
'SimplePropertyDescriptor.java',
9195
'UnreachableBrowserException.java',
9296
'UselessFileDetector.java',
97+
'W3CHandshakeResponse.java',
9398
'html5/RemoteApplicationCache.java',
9499
'html5/RemoteLocalStorage.java',
95100
'html5/RemoteLocationContext.java',
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.remote;
19+
20+
import java.util.Map;
21+
import java.util.Optional;
22+
import java.util.function.Function;
23+
24+
class Gecko013ProtocolResponse implements HandshakeResponse {
25+
26+
private final Function<InitialHandshakeResponse, Optional<ProtocolHandshake.Result>> error = tuple -> {
27+
Object rawMessage = tuple.getData().get("message");
28+
Object rawError = tuple.getData().get("error");
29+
30+
if (!(rawError instanceof String) || (!(rawMessage instanceof String))) {
31+
return Optional.empty();
32+
}
33+
34+
Response response = new Response();
35+
response.setState((String) rawError);
36+
response.setStatus(new ErrorCodes().toStatus((String) rawError, Optional.of(tuple.getStatusCode())));
37+
response.setValue(rawMessage);
38+
39+
new ErrorHandler().throwIfResponseFailed(response, tuple.getRequestDuration().toMillis());
40+
// We never get this far
41+
return Optional.empty();
42+
};
43+
44+
private final Function<InitialHandshakeResponse, Optional<ProtocolHandshake.Result>> success = tuple -> {
45+
if (tuple.getData().containsKey("status")) {
46+
return Optional.empty();
47+
}
48+
49+
// Some versions of geckodriver returned "{value: {sessionId: '', value: {}}". Add check.
50+
Object rawSessionId = tuple.getData().get("sessionId");
51+
Object rawCapabilities = tuple.getData().get("value");
52+
53+
if (rawCapabilities instanceof Map) {
54+
Map<?, ?> map = (Map<?, ?>) rawCapabilities;
55+
if (map.containsKey("sessionId") && map.containsKey("value")) {
56+
rawSessionId = map.get("sessionId");
57+
rawCapabilities = map.get("value");
58+
}
59+
}
60+
61+
if (!(rawSessionId instanceof String) || !(rawCapabilities instanceof Map)) {
62+
return Optional.empty();
63+
}
64+
65+
66+
if (((Map<?, ?>) rawCapabilities).containsKey("value")) {
67+
Object newValue = ((Map<?, ?>) rawCapabilities).get("value");
68+
if (newValue instanceof Map) {
69+
rawCapabilities = newValue;
70+
}
71+
}
72+
73+
// Ensure Map keys are all strings.
74+
for (Object key : ((Map<?, ?>) rawCapabilities).keySet()) {
75+
if (!(key instanceof String)) {
76+
return Optional.empty();
77+
}
78+
}
79+
80+
@SuppressWarnings("unchecked") Map<String, Object> caps = (Map<String, Object>) rawCapabilities;
81+
82+
String sessionId = (String) rawSessionId;
83+
return Optional.of(new ProtocolHandshake.Result(Dialect.W3C, sessionId, caps));
84+
};
85+
86+
87+
@Override
88+
public Function<InitialHandshakeResponse, Optional<ProtocolHandshake.Result>> getResponseFunction() {
89+
return resp -> {
90+
Optional<ProtocolHandshake.Result> result = error.apply(resp);
91+
if (!result.isPresent()) {
92+
result = success.apply(resp);
93+
}
94+
return result;
95+
};
96+
}
97+
98+
99+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package org.openqa.selenium.remote;
2+
3+
import java.util.Optional;
4+
import java.util.function.Function;
5+
6+
interface HandshakeResponse {
7+
Function<InitialHandshakeResponse, Optional<ProtocolHandshake.Result>> getResponseFunction();
8+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.remote;
19+
20+
import com.google.common.base.Preconditions;
21+
22+
import java.time.Duration;
23+
import java.util.Map;
24+
25+
class InitialHandshakeResponse {
26+
private final Duration requestDuration;
27+
private final int httpStatusCode;
28+
private final Map<?, ?> data;
29+
30+
public InitialHandshakeResponse(long millis, int statusCode, Map<?, ?> data) {
31+
this.requestDuration = Duration.ofMillis(millis);
32+
this.httpStatusCode = statusCode;
33+
this.data = Preconditions.checkNotNull(data);
34+
}
35+
36+
public Duration getRequestDuration() {
37+
return requestDuration;
38+
}
39+
40+
public int getStatusCode() {
41+
return httpStatusCode;
42+
}
43+
44+
public Map<?, ?> getData() {
45+
return data;
46+
}
47+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.remote;
19+
20+
21+
import java.util.Map;
22+
import java.util.Optional;
23+
import java.util.function.Function;
24+
25+
class JsonWireProtocolResponse implements HandshakeResponse {
26+
27+
private final Function<InitialHandshakeResponse, Optional<ProtocolHandshake.Result>> error = tuple -> {
28+
if (!(tuple.getData().containsKey("status"))) {
29+
return Optional.empty();
30+
}
31+
32+
Object rawStatus = tuple.getData().get("status");
33+
if (!(rawStatus instanceof Number)) {
34+
return Optional.empty();
35+
}
36+
37+
if (((Number) rawStatus).intValue() == 0) {
38+
return Optional.empty();
39+
}
40+
41+
if (!(tuple.getData().containsKey("value"))) {
42+
return Optional.empty();
43+
}
44+
Object value = tuple.getData().get("value");
45+
if (!(value instanceof Map)) {
46+
return Optional.empty();
47+
}
48+
49+
Response response = new Response(null);
50+
response.setStatus(((Number) rawStatus).intValue());
51+
response.setValue(value);
52+
53+
new ErrorHandler().throwIfResponseFailed(response, tuple.getRequestDuration().toMillis());
54+
// We never get this far.
55+
return Optional.empty();
56+
};
57+
58+
private final Function<InitialHandshakeResponse, Optional<ProtocolHandshake.Result>> success = tuple -> {
59+
Object rawStatus = tuple.getData().get("status");
60+
if (!(rawStatus instanceof Number)) {
61+
return Optional.empty();
62+
}
63+
64+
if (0 != ((Number) rawStatus).intValue()) {
65+
return Optional.empty();
66+
}
67+
68+
Object rawSessionId = tuple.getData().get("sessionId");
69+
Object rawCapabilities = tuple.getData().get("value");
70+
71+
if (!(rawSessionId instanceof String) || !(rawCapabilities instanceof Map)) {
72+
return Optional.empty();
73+
}
74+
75+
// Ensure Map keys are all strings.
76+
for (Object key : ((Map<?, ?>) rawCapabilities).keySet()) {
77+
if (!(key instanceof String)) {
78+
return Optional.empty();
79+
}
80+
}
81+
82+
@SuppressWarnings("unchecked") Map<String, Object> caps = (Map<String, Object>) rawCapabilities;
83+
84+
String sessionId = (String) rawSessionId;
85+
return Optional.of(new ProtocolHandshake.Result(Dialect.OSS, sessionId, caps));
86+
};
87+
88+
@Override
89+
public Function<InitialHandshakeResponse, Optional<ProtocolHandshake.Result>> getResponseFunction() {
90+
return resp -> {
91+
Optional<ProtocolHandshake.Result> result = error.apply(resp);
92+
if (!result.isPresent()) {
93+
result = success.apply(resp);
94+
}
95+
return result;
96+
};
97+
}
98+
}

0 commit comments

Comments
 (0)