diff --git a/common/src/web/devToolsSecurityTest b/common/src/web/devToolsSecurityTest new file mode 100644 index 0000000000000..7244bfac07626 --- /dev/null +++ b/common/src/web/devToolsSecurityTest @@ -0,0 +1,10 @@ + + + + + + +

Security Test

+ + + diff --git a/java/client/src/org/openqa/selenium/devtools/network/model/CallFrame.java b/java/client/src/org/openqa/selenium/devtools/network/model/CallFrame.java index 9d5758c315cd3..8e144c2c5b2cd 100644 --- a/java/client/src/org/openqa/selenium/devtools/network/model/CallFrame.java +++ b/java/client/src/org/openqa/selenium/devtools/network/model/CallFrame.java @@ -115,7 +115,7 @@ public void setColumnNumber(Integer columnNumber) { this.columnNumber = columnNumber; } - public static CallFrame parseCallFrame(JsonInput input) { + private static CallFrame fromJson(JsonInput input) { String functionName = null; String scriptId = null; String callFrameUrl = null; diff --git a/java/client/src/org/openqa/selenium/devtools/network/model/Initiator.java b/java/client/src/org/openqa/selenium/devtools/network/model/Initiator.java index be7651680bce1..77595247aff7c 100644 --- a/java/client/src/org/openqa/selenium/devtools/network/model/Initiator.java +++ b/java/client/src/org/openqa/selenium/devtools/network/model/Initiator.java @@ -101,7 +101,7 @@ public void setLineNumber(Double lineNumber) { this.lineNumber = lineNumber; } - public static Initiator parseInitiator(JsonInput input) { + private static Initiator fromJson(JsonInput input) { InitiatorType initiatorType = null; StackTrace stack = null; diff --git a/java/client/src/org/openqa/selenium/devtools/network/model/RequestIntercepted.java b/java/client/src/org/openqa/selenium/devtools/network/model/RequestIntercepted.java index 8a80906a58f43..40853004b4bf8 100644 --- a/java/client/src/org/openqa/selenium/devtools/network/model/RequestIntercepted.java +++ b/java/client/src/org/openqa/selenium/devtools/network/model/RequestIntercepted.java @@ -113,7 +113,7 @@ private RequestIntercepted(InterceptionId interceptionId, this.requestId = requestId; } - public static RequestIntercepted fromJson(JsonInput input) { + private static RequestIntercepted fromJson(JsonInput input) { InterceptionId interceptionId = new InterceptionId(input.nextString()); Request request = null; String frameId = null; diff --git a/java/client/src/org/openqa/selenium/devtools/network/model/RequestWillBeSent.java b/java/client/src/org/openqa/selenium/devtools/network/model/RequestWillBeSent.java index f653c50c59338..33ccf4b38f9aa 100644 --- a/java/client/src/org/openqa/selenium/devtools/network/model/RequestWillBeSent.java +++ b/java/client/src/org/openqa/selenium/devtools/network/model/RequestWillBeSent.java @@ -142,7 +142,7 @@ private static RequestWillBeSent fromJson(JsonInput input) { break; case "initiator": - initiator = Initiator.parseInitiator(input); + initiator = input.read(Initiator.class); break; case "redirectResponse": diff --git a/java/client/src/org/openqa/selenium/devtools/network/model/Response.java b/java/client/src/org/openqa/selenium/devtools/network/model/Response.java index a2d42263ae841..94192b46e6a49 100644 --- a/java/client/src/org/openqa/selenium/devtools/network/model/Response.java +++ b/java/client/src/org/openqa/selenium/devtools/network/model/Response.java @@ -368,7 +368,7 @@ public void setSecurityDetails(SecurityDetails securityDetails) { this.securityDetails = securityDetails; } - public static Response fromJson(JsonInput input) { + private static Response fromJson(JsonInput input) { Response response; input.beginObject(); diff --git a/java/client/src/org/openqa/selenium/devtools/network/model/ResponseReceived.java b/java/client/src/org/openqa/selenium/devtools/network/model/ResponseReceived.java index 9aac573f58b41..fc62f6fb1f5ef 100644 --- a/java/client/src/org/openqa/selenium/devtools/network/model/ResponseReceived.java +++ b/java/client/src/org/openqa/selenium/devtools/network/model/ResponseReceived.java @@ -69,7 +69,7 @@ private ResponseReceived(RequestId requestId, } - public static ResponseReceived fromJson(JsonInput input) { + private static ResponseReceived fromJson(JsonInput input) { RequestId requestId = new RequestId(input.nextString()); LoaderId loaderId = null; MonotonicTime timestamp = null; diff --git a/java/client/src/org/openqa/selenium/devtools/network/model/StackTrace.java b/java/client/src/org/openqa/selenium/devtools/network/model/StackTrace.java index 2b33057accf39..3c8c9264887a5 100644 --- a/java/client/src/org/openqa/selenium/devtools/network/model/StackTrace.java +++ b/java/client/src/org/openqa/selenium/devtools/network/model/StackTrace.java @@ -121,7 +121,7 @@ private static StackTrace fromJson(JsonInput input) { input.beginArray(); callFrames = new ArrayList<>(); while (input.hasNext()) { - callFrames.add(CallFrame.parseCallFrame(input)); + callFrames.add(input.read(CallFrame.class)); } input.endArray(); break; diff --git a/java/client/src/org/openqa/selenium/devtools/network/model/WebSocketCreated.java b/java/client/src/org/openqa/selenium/devtools/network/model/WebSocketCreated.java index 039405bf93ae6..f6f2cfb55aa3d 100644 --- a/java/client/src/org/openqa/selenium/devtools/network/model/WebSocketCreated.java +++ b/java/client/src/org/openqa/selenium/devtools/network/model/WebSocketCreated.java @@ -70,7 +70,7 @@ private static WebSocketCreated fromJson(JsonInput input) { url = input.nextString(); break; case "initiator": - initiator = Initiator.parseInitiator(input); + initiator = input.read(Initiator.class); break; default: input.skipValue(); diff --git a/java/client/src/org/openqa/selenium/devtools/profiler/model/ProfileNode.java b/java/client/src/org/openqa/selenium/devtools/profiler/model/ProfileNode.java index 0d6c596500e3d..8b42d1e668c4f 100644 --- a/java/client/src/org/openqa/selenium/devtools/profiler/model/ProfileNode.java +++ b/java/client/src/org/openqa/selenium/devtools/profiler/model/ProfileNode.java @@ -81,7 +81,7 @@ public static ProfileNode fromJson(JsonInput input) { id = input.read(Integer.class); break; case "callFrame": - callFrame = CallFrame.parseCallFrame(input); + callFrame = input.read(CallFrame.class); break; case "hitCount": hitCount = input.read(Integer.class); diff --git a/java/client/src/org/openqa/selenium/devtools/security/Security.java b/java/client/src/org/openqa/selenium/devtools/security/Security.java new file mode 100644 index 0000000000000..1b819507b8563 --- /dev/null +++ b/java/client/src/org/openqa/selenium/devtools/security/Security.java @@ -0,0 +1,61 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.openqa.selenium.devtools.security; + +import static org.openqa.selenium.devtools.ConverterFunctions.map; + +import com.google.common.collect.ImmutableMap; + +import org.openqa.selenium.devtools.Command; +import org.openqa.selenium.devtools.Event; +import org.openqa.selenium.devtools.security.model.SecurityStateChanged; + +public class Security { + + private final static String DOMAIN_NAME = "Security"; + + /** + * Disables tracking security state changes. + */ + public static Command disable() { + return new Command<>(DOMAIN_NAME + ".disable", ImmutableMap.of()); + } + + /** + * Enables tracking security state changes. + */ + public static Command enable() { + return new Command<>(DOMAIN_NAME + ".enable", ImmutableMap.of()); + } + + /** + * Enable/disable whether all certificate errors should be ignored. (EXPERIMENTAL) + */ + public static Command setIgnoreCertificateErrors(boolean ignore) { + return new Command<>(DOMAIN_NAME + ".setIgnoreCertificateErrors", + ImmutableMap.of("ignore", ignore)); + } + + /** + * The security state of the page changed. + */ + public static Event securityStateChanged() { + return new Event<>(DOMAIN_NAME + ".securityStateChanged", + map("securityState", SecurityStateChanged.class)); + } + +} diff --git a/java/client/src/org/openqa/selenium/devtools/security/model/SecurityStateChanged.java b/java/client/src/org/openqa/selenium/devtools/security/model/SecurityStateChanged.java new file mode 100644 index 0000000000000..cc653ec08457d --- /dev/null +++ b/java/client/src/org/openqa/selenium/devtools/security/model/SecurityStateChanged.java @@ -0,0 +1,104 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.openqa.selenium.devtools.security.model; + +import static java.util.Objects.requireNonNull; + +import com.google.common.reflect.TypeToken; + +import org.openqa.selenium.devtools.network.model.SecurityState; +import org.openqa.selenium.json.JsonInput; + +import java.util.List; + +public class SecurityStateChanged { + + /** + * Security state + */ + private SecurityState securityState; + + /** + * True if the page was loaded over cryptographic transport such as HTTPS. + */ + private boolean schemeIsCryptographic; + + /** + * List of explanations for the security state. + * If the overall security state is insecure or warning, at least one corresponding + * explanation should be included. + */ + private List securityStateExplanations; + + /** + * Overrides user-visible description of the state. + */ + private String summary; + + private SecurityStateChanged(SecurityState securityState, boolean schemeIsCryptographic, + List securityStateExplanations, + String summary) { + this.securityState = + requireNonNull(securityState, "'securityState' is required for SecurityStateChanged"); + this.schemeIsCryptographic = schemeIsCryptographic; + this.securityStateExplanations = securityStateExplanations; + this.summary = summary; + } + + private static SecurityStateChanged fromJson(JsonInput input) { + SecurityState securityState = SecurityState.valueOf(input.nextString()); + boolean schemeIsCryptographic = false; + List securityStateExplanations = null; + String summary = null; + while (input.hasNext()) { + switch (input.nextName()) { + case "schemeIsCryptographic": + schemeIsCryptographic = input.nextBoolean(); + break; + case "securityStateExplanations": + securityStateExplanations = input.read(new TypeToken>() { + }.getType()); + break; + case "summary": + summary = input.nextString(); + break; + default: + input.skipValue(); + break; + } + } + return new SecurityStateChanged(securityState, schemeIsCryptographic, securityStateExplanations, + summary); + } + + public SecurityState getSecurityState() { + return securityState; + } + + public boolean isSchemeIsCryptographic() { + return schemeIsCryptographic; + } + + public List getSecurityStateExplanations() { + return securityStateExplanations; + } + + public String getSummary() { + return summary; + } + +} diff --git a/java/client/src/org/openqa/selenium/devtools/security/model/SecurityStateExplanation.java b/java/client/src/org/openqa/selenium/devtools/security/model/SecurityStateExplanation.java new file mode 100644 index 0000000000000..228abd8b231dd --- /dev/null +++ b/java/client/src/org/openqa/selenium/devtools/security/model/SecurityStateExplanation.java @@ -0,0 +1,155 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.openqa.selenium.devtools.security.model; + +import static java.util.Objects.requireNonNull; + +import com.google.common.reflect.TypeToken; + +import org.openqa.selenium.devtools.network.model.MixedContentType; +import org.openqa.selenium.devtools.network.model.SecurityState; +import org.openqa.selenium.json.JsonInput; + +import java.util.List; + +public class SecurityStateExplanation { + + /** + * Security state representing the severity of the factor being explained. + */ + private SecurityState securityState; + + /** + * Title describing the type of factor. + */ + private String title; + + /** + * Short phrase describing the type of factor. + */ + private String summary; + + /** + * Full text explanation of the factor. + */ + private String description; + + /** + * The type of mixed content described by the explanation. + */ + private MixedContentType mixedContentType; + + /** + * Page certificate. + */ + private List certificate; + + /** + * Recommendations to fix any issues. + */ + private List recommendations; + + private SecurityStateExplanation( + SecurityState securityState, String title, String summary, String description, + MixedContentType mixedContentType, List certificate, + List recommendations) { + this.securityState = + requireNonNull(securityState, "'securityState' is required for SecurityStateExplanation"); + this.title = requireNonNull(title, "'title' is required for SecurityStateExplanation"); + ; + this.summary = requireNonNull(summary, "'summary' is required for SecurityStateExplanation"); + this.description = + requireNonNull(description, "'description' is required for SecurityStateExplanation"); + this.mixedContentType = + requireNonNull(mixedContentType, + "'mixedContentType' is required for SecurityStateExplanation"); + this.certificate = + requireNonNull(certificate, "'certificate' is required for SecurityStateExplanation"); + this.recommendations = recommendations; + } + + private static SecurityStateExplanation fromJson(JsonInput input) { + SecurityState securityState = null; + String title = null; + String summary = null; + String description = null; + MixedContentType mixedContentType = null; + List certificate = null; + List recommendations = null; + while (input.hasNext()) { + switch (input.nextName()) { + case "securityState": + securityState = SecurityState.valueOf(input.nextString()); + break; + case "title": + title = input.nextString(); + break; + case "summary": + summary = input.nextString(); + break; + case "description": + description = input.nextString(); + break; + case "mixedContentType": + mixedContentType = MixedContentType.fromString(input.nextString()); + break; + case "certificate": + certificate = input.read(new TypeToken>() { + }.getType()); + break; + case "recommendations": + recommendations = input.read(new TypeToken>() { + }.getType()); + break; + default: + input.skipValue(); + break; + } + } + return new SecurityStateExplanation(securityState, title, summary, description, + mixedContentType, certificate, recommendations); + } + + public SecurityState getSecurityState() { + return securityState; + } + + public String getTitle() { + return title; + } + + public String getSummary() { + return summary; + } + + public String getDescription() { + return description; + } + + public MixedContentType getMixedContentType() { + return mixedContentType; + } + + public List getCertificate() { + return certificate; + } + + public List getRecommendations() { + return recommendations; + } + +} diff --git a/java/client/test/org/openqa/selenium/devtools/ChromeDevToolsLogTest.java b/java/client/test/org/openqa/selenium/devtools/ChromeDevToolsLogTest.java index 85d1075e8d3a0..445a91c94b105 100644 --- a/java/client/test/org/openqa/selenium/devtools/ChromeDevToolsLogTest.java +++ b/java/client/test/org/openqa/selenium/devtools/ChromeDevToolsLogTest.java @@ -25,9 +25,6 @@ import org.junit.Assert; import org.junit.Test; -/** - * Created by aohana - */ public class ChromeDevToolsLogTest extends ChromeDevToolsTestBase { @Test diff --git a/java/client/test/org/openqa/selenium/devtools/ChromeDevToolsSecurityTest.java b/java/client/test/org/openqa/selenium/devtools/ChromeDevToolsSecurityTest.java new file mode 100644 index 0000000000000..b68ccafdabe69 --- /dev/null +++ b/java/client/test/org/openqa/selenium/devtools/ChromeDevToolsSecurityTest.java @@ -0,0 +1,61 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.openqa.selenium.devtools; + +import static org.openqa.selenium.devtools.security.Security.disable; +import static org.openqa.selenium.devtools.security.Security.enable; +import static org.openqa.selenium.devtools.security.Security.setIgnoreCertificateErrors; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.devtools.security.Security; + +public class ChromeDevToolsSecurityTest extends ChromeDevToolsTestBase { + + @Test + public void loadInsecureWebsite() { + + devTools.send(enable()); + + devTools.send(setIgnoreCertificateErrors(false)); + + devTools.addListener(Security.securityStateChanged(), + securityStateChanged -> Assert.assertEquals(true, securityStateChanged + .getSummary().contains("This page has a non-HTTPS secure origin"))); + + chromeDriver.get(appServer.whereIs("devToolsSecurityTest")); + + Assert.assertEquals(true, chromeDriver.getPageSource().contains("Security Test")); + + devTools.send(disable()); + + } + + @Test + public void loadSecureWebsite() { + + devTools.send(enable()); + + devTools.send(setIgnoreCertificateErrors(true)); + + chromeDriver.get(appServer.whereIsSecure("devToolsSecurityTest")); + + Assert.assertEquals(true, chromeDriver.getPageSource().contains("Security Test")); + + } + +} diff --git a/java/client/test/org/openqa/selenium/devtools/ChromeDevToolsTestBase.java b/java/client/test/org/openqa/selenium/devtools/ChromeDevToolsTestBase.java index e3f55ce130c13..5717005c132ef 100644 --- a/java/client/test/org/openqa/selenium/devtools/ChromeDevToolsTestBase.java +++ b/java/client/test/org/openqa/selenium/devtools/ChromeDevToolsTestBase.java @@ -21,9 +21,6 @@ import org.junit.Before; import org.openqa.selenium.chrome.ChromeDriver; -/** - * Created by aohana - */ public abstract class ChromeDevToolsTestBase extends DevToolsTestBase { ChromeDriver chromeDriver; diff --git a/java/client/test/org/openqa/selenium/devtools/DevToolsTests.java b/java/client/test/org/openqa/selenium/devtools/DevToolsTests.java index 64c6f2f9f084d..c75d59b189ee5 100644 --- a/java/client/test/org/openqa/selenium/devtools/DevToolsTests.java +++ b/java/client/test/org/openqa/selenium/devtools/DevToolsTests.java @@ -27,7 +27,8 @@ ChromeDevToolsNetworkTest.class, ChromeDevToolsPerformanceTest.class, ChromeDevToolsConsoleTest.class, - ChromeDevToolsLogTest.class + ChromeDevToolsLogTest.class, + ChromeDevToolsSecurityTest.class }) public class DevToolsTests {