diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index ac01736db281..a396ecc41b70 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -3879,10 +3879,10 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI, } if (nsCOMPtr loadURIDelegate = GetLoadURIDelegate()) { + nsresult code = isHttpsOnlyError ? NS_ERROR_HTTPS_ONLY : aError; nsCOMPtr errorPageURI; - rv = loadURIDelegate->HandleLoadError( - aURI, (isHttpsOnlyError ? NS_ERROR_HTTPS_ONLY : aError), - NS_ERROR_GET_MODULE(aError), getter_AddRefs(errorPageURI)); + rv = loadURIDelegate->HandleLoadError(aURI, code, NS_ERROR_GET_MODULE(code), + getter_AddRefs(errorPageURI)); // If the docshell is going away there's no point in showing an error page. if (NS_FAILED(rv) || mIsBeingDestroyed) { *aDisplayedErrorPage = false; diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt index 7d894f8958ea..d6dc1911880f 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt @@ -354,7 +354,7 @@ class NavigationDelegateTest : BaseSessionTest() { mainSession.forCallbacksDuringWait(object : NavigationDelegate { @AssertCalled(count = 1) override fun onLoadError(session: GeckoSession, uri: String?, error: WebRequestError): GeckoResult? { - assertThat("categories should match", error.category, equalTo(WebRequestError.ERROR_CATEGORY_SECURITY)) + assertThat("categories should match", error.category, equalTo(WebRequestError.ERROR_CATEGORY_NETWORK)) assertThat("codes should match", error.code, equalTo(WebRequestError.ERROR_HTTPS_ONLY)) return null } @@ -424,7 +424,7 @@ class NavigationDelegateTest : BaseSessionTest() { privateSession.forCallbacksDuringWait(object : NavigationDelegate { @AssertCalled(count = 1) override fun onLoadError(session: GeckoSession, uri: String?, error: WebRequestError): GeckoResult? { - assertThat("categories should match", error.category, equalTo(WebRequestError.ERROR_CATEGORY_SECURITY)) + assertThat("categories should match", error.category, equalTo(WebRequestError.ERROR_CATEGORY_NETWORK)) assertThat("codes should match", error.code, equalTo(WebRequestError.ERROR_HTTPS_ONLY)) return null } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/XPCOMError.jinja b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/XPCOMError.jinja new file mode 100644 index 000000000000..f704bbc77500 --- /dev/null +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/XPCOMError.jinja @@ -0,0 +1,38 @@ +/* -*- Mode: Java; c-basic-offset: 2; tab-width: 4; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.util; + +public final class XPCOMError { + /** Check if the error code corresponds to a failure */ + public static boolean failed(long err) { + return (err & 0x80000000L) != 0; + } + + /** Check if the error code corresponds to a failure */ + public static boolean succeeded(long err) { + return !failed(err); + } + + /** Extract the error code part of the error message */ + public static int getErrorCode(long err) { + return (int)(err & 0xffffL); + } + + /** Extract the error module part of the error message */ + public static int getErrorModule(long err) { + return (int)(((err >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 0x1fffL); + } + + public static final int NS_ERROR_MODULE_BASE_OFFSET = {{ MODULE_BASE_OFFSET }}; + +{% for mod, val in modules %} + public static final int NS_ERROR_MODULE_{{ mod }} = {{ val }}; +{% endfor %} + +{% for error, val in errors %} + public static final long {{ error }} = 0x{{ "%X" % val }}L; +{% endfor %} +} diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequestError.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequestError.java index e43ddbf543c5..19080fa3fc15 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequestError.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequestError.java @@ -18,6 +18,7 @@ import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Arrays; import org.mozilla.gecko.annotation.WrapForJNI; +import org.mozilla.gecko.util.XPCOMError; /** * WebRequestError is simply a container for error codes and categories used by {@link @@ -245,8 +246,10 @@ public class WebRequestError extends Exception { final int geckoErrorModule, final int geckoErrorClass, final byte[] certificateBytes) { - final int code = convertGeckoError(geckoError, geckoErrorModule, geckoErrorClass); - final int category = getErrorCategory(geckoErrorModule, code); + // XXX: the geckoErrorModule argument is redundant + assert geckoErrorModule == XPCOMError.getErrorModule(geckoError); + final int code = convertGeckoError(geckoError, geckoErrorClass); + final int category = getErrorCategory(XPCOMError.getErrorModule(geckoError), code); X509Certificate certificate = null; if (certificateBytes != null) { try { @@ -266,8 +269,7 @@ public class WebRequestError extends Exception { @WrapForJNI /* package */ static @ErrorCategory int getErrorCategory( final long errorModule, final @Error int error) { - // Match flags with XPCOM ErrorList.h. - if (errorModule == 21) { + if (errorModule == XPCOMError.NS_ERROR_MODULE_SECURITY) { return ERROR_CATEGORY_SECURITY; } return error & 0xF; @@ -275,87 +277,86 @@ public class WebRequestError extends Exception { @WrapForJNI /* package */ static @Error int convertGeckoError( - final long geckoError, final int geckoErrorModule, final int geckoErrorClass) { - // Match flags with XPCOM ErrorList.h. + final long geckoError, final int geckoErrorClass) { // safebrowsing - if (geckoError == 0x805D001FL) { + if (geckoError == XPCOMError.NS_ERROR_PHISHING_URI) { return ERROR_SAFEBROWSING_PHISHING_URI; } - if (geckoError == 0x805D001EL) { + if (geckoError == XPCOMError.NS_ERROR_MALWARE_URI) { return ERROR_SAFEBROWSING_MALWARE_URI; } - if (geckoError == 0x805D0023L) { + if (geckoError == XPCOMError.NS_ERROR_UNWANTED_URI) { return ERROR_SAFEBROWSING_UNWANTED_URI; } - if (geckoError == 0x805D0026L) { + if (geckoError == XPCOMError.NS_ERROR_HARMFUL_URI) { return ERROR_SAFEBROWSING_HARMFUL_URI; } // content - if (geckoError == 0x805E0010L) { + if (geckoError == XPCOMError.NS_ERROR_CONTENT_CRASHED) { return ERROR_CONTENT_CRASHED; } - if (geckoError == 0x804B001BL) { + if (geckoError == XPCOMError.NS_ERROR_INVALID_CONTENT_ENCODING) { return ERROR_INVALID_CONTENT_ENCODING; } - if (geckoError == 0x804B004AL) { + if (geckoError == XPCOMError.NS_ERROR_UNSAFE_CONTENT_TYPE) { return ERROR_UNSAFE_CONTENT_TYPE; } - if (geckoError == 0x804B001DL) { + if (geckoError == XPCOMError.NS_ERROR_CORRUPTED_CONTENT) { return ERROR_CORRUPTED_CONTENT; } // network - if (geckoError == 0x804B0014L) { + if (geckoError == XPCOMError.NS_ERROR_NET_RESET) { return ERROR_NET_RESET; } - if (geckoError == 0x804B0047L) { + if (geckoError == XPCOMError.NS_ERROR_NET_RESET) { return ERROR_NET_INTERRUPT; } - if (geckoError == 0x804B000EL) { + if (geckoError == XPCOMError.NS_ERROR_NET_TIMEOUT) { return ERROR_NET_TIMEOUT; } - if (geckoError == 0x804B000DL) { + if (geckoError == XPCOMError.NS_ERROR_CONNECTION_REFUSED) { return ERROR_CONNECTION_REFUSED; } - if (geckoError == 0x804B0033L) { + if (geckoError == XPCOMError.NS_ERROR_UNKNOWN_SOCKET_TYPE) { return ERROR_UNKNOWN_SOCKET_TYPE; } - if (geckoError == 0x804B001FL) { + if (geckoError == XPCOMError.NS_ERROR_REDIRECT_LOOP) { return ERROR_REDIRECT_LOOP; } - if (geckoError == 0x804B0056L) { + if (geckoError == XPCOMError.NS_ERROR_HTTPS_ONLY) { return ERROR_HTTPS_ONLY; } - if (geckoError == 0x804B0010L) { + if (geckoError == XPCOMError.NS_ERROR_OFFLINE) { return ERROR_OFFLINE; } - if (geckoError == 0x804B0013L) { + if (geckoError == XPCOMError.NS_ERROR_PORT_ACCESS_NOT_ALLOWED) { return ERROR_PORT_BLOCKED; } // uri - if (geckoError == 0x804B0012L) { + if (geckoError == XPCOMError.NS_ERROR_UNKNOWN_PROTOCOL) { return ERROR_UNKNOWN_PROTOCOL; } - if (geckoError == 0x804B001EL) { + if (geckoError == XPCOMError.NS_ERROR_UNKNOWN_HOST) { return ERROR_UNKNOWN_HOST; } - if (geckoError == 0x804B000AL) { + if (geckoError == XPCOMError.NS_ERROR_MALFORMED_URI) { return ERROR_MALFORMED_URI; } - if (geckoError == 0x80520012L) { + if (geckoError == XPCOMError.NS_ERROR_FILE_NOT_FOUND) { return ERROR_FILE_NOT_FOUND; } - if (geckoError == 0x80520015L) { + if (geckoError == XPCOMError.NS_ERROR_FILE_ACCESS_DENIED) { return ERROR_FILE_ACCESS_DENIED; } // proxy - if (geckoError == 0x804B002AL) { + if (geckoError == XPCOMError.NS_ERROR_UNKNOWN_PROXY_HOST) { return ERROR_UNKNOWN_PROXY_HOST; } - if (geckoError == 0x804B0048L) { + if (geckoError == XPCOMError.NS_ERROR_PROXY_CONNECTION_REFUSED) { return ERROR_PROXY_CONNECTION_REFUSED; } - if (geckoErrorModule == 21) { + if (XPCOMError.getErrorModule(geckoError) == XPCOMError.NS_ERROR_MODULE_SECURITY) { if (geckoErrorClass == 1) { return ERROR_SECURITY_SSL; } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md index ecd40e04f4a8..c30a163eeab7 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md @@ -18,12 +18,15 @@ exclude: true ([bug 1499635]({{bugzilla}}1499635)) - Deprecated [`onLocationChange(2)`][102.3], please use [`onLocationChange(3)`][102.4]. - Added [`GeckoSession.setPriorityHint`][102.5] function to set the session to either high priority or default. +- [`WebRequestError.ERROR_HTTPS_ONLY`][102.6] now has error category + `ERROR_CATEGORY_NETWORK` rather than `ERROR_CATEGORY_SECURITY`. [102.1]: {{javadoc_uri}}/GeckoSession.PromptDelegate.DateTimePrompt.html#stepValue [102.2]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date#step [102.3]: {{javadoc_uri}}/GeckoSession.NavigationDelegate.html#onLocationChange(org.mozilla.geckoview.GeckoSession,java.lang.String) [102.4]: {{javadoc_uri}}/GeckoSession.NavigationDelegate.html#onLocationChange(org.mozilla.geckoview.GeckoSession,java.lang.String,java.util.List) [102.5]: {{javadoc_uri}}/GeckoSession.html#setPriorityHint(int) +[102.6]: {{javadoc_uri}}/WebRequestError.html#ERROR_HTTPS_ONLY ## v101 - Added [`GeckoDisplay.surfaceChanged`][101.1] function taking new type [`GeckoDisplay.SurfaceInfo`][101.2]. diff --git a/mobile/android/moz.build b/mobile/android/moz.build index dfc06746f631..e72b8a34328e 100644 --- a/mobile/android/moz.build +++ b/mobile/android/moz.build @@ -46,6 +46,13 @@ GeneratedFile( flags=flags, ) +GeneratedFile( + ("geckoview/src/main/java/org/mozilla/gecko/util/XPCOMError.java",), + script="/xpcom/base/ErrorList.py", + entry_point="gen_jinja", + inputs=["geckoview/src/main/java/org/mozilla/gecko/util/XPCOMError.jinja"], +) + CONFIGURE_SUBST_FILES += ["installer/Makefile"] DIRS += [ diff --git a/xpcom/base/ErrorList.py b/xpcom/base/ErrorList.py index f878aee4b470..c8ae52c16c80 100755 --- a/xpcom/base/ErrorList.py +++ b/xpcom/base/ErrorList.py @@ -1372,3 +1372,27 @@ use super::nsresult; for error, val in errors.items(): output.write("pub const {}: nsresult = nsresult(0x{:X});\n".format(error, val)) + + +def gen_jinja(output, input_filename): + # This is used to generate Java code for error lists, and can be expanded to + # other required contexts in the future if desired. + from jinja2 import Environment, FileSystemLoader, StrictUndefined + import os + + # FileSystemLoader requires the path to the directory containing templates, + # not the file name of the template itself. + (path, leaf) = os.path.split(input_filename) + env = Environment( + loader=FileSystemLoader(path, encoding="utf-8"), + undefined=StrictUndefined, + ) + tpl = env.get_template(leaf) + + context = { + "MODULE_BASE_OFFSET": MODULE_BASE_OFFSET, + "modules": ((mod, val.num) for mod, val in modules.items()), + "errors": errors.items(), + } + + tpl.stream(context).dump(output, encoding="utf-8")