Skip to content

Commit

Permalink
Issue mozilla-mobile#1076: Bring back error handling functionality
Browse files Browse the repository at this point in the history
Co-authored-by: Jonathan Almeida <[email protected]>
  • Loading branch information
csadilek and jonalmeida committed Sep 13, 2018
1 parent 3140b5e commit 0e498af
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 12 deletions.
17 changes: 5 additions & 12 deletions app/src/main/java/org/mozilla/focus/browser/ErrorPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.focus.browser;

import android.content.Context;
import android.content.res.Resources;
import android.support.v4.util.ArrayMap;
import android.support.v4.util.Pair;

import android.util.SparseArray;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import org.mozilla.focus.R;
import org.mozilla.focus.utils.HtmlLoader;
Expand Down Expand Up @@ -85,7 +85,7 @@ public static boolean supportsErrorCode(final int errorCode) {
return (errorDescriptionMap.get(errorCode) != null);
}

public static void loadErrorPage(final WebView webView, final String desiredURL, final int errorCode) {
public static String loadErrorPage(final Context context, final String desiredURL, final int errorCode) {
final Pair<Integer, Integer> errorResourceIDs = errorDescriptionMap.get(errorCode);

if (errorResourceIDs == null) {
Expand All @@ -104,25 +104,18 @@ public static void loadErrorPage(final WebView webView, final String desiredURL,
// https://code.google.com/p/android/issues/detail?id=211768 (this breaks loading css via file:///
// references when running debug builds, and probably klar too) - which means this wouldn't
// be possible even if we hacked around the mixed content issues.
final String cssString = HtmlLoader.loadResourceFile(webView.getContext(), R.raw.errorpage_style, null);
final String cssString = HtmlLoader.loadResourceFile(context, R.raw.errorpage_style, null);

final Map<String, String> substitutionMap = new ArrayMap<>();

final Resources resources = webView.getContext().getResources();
final Resources resources = context.getResources();

substitutionMap.put("%page-title%", resources.getString(R.string.errorpage_title));
substitutionMap.put("%button%", resources.getString(R.string.errorpage_refresh));

substitutionMap.put("%messageShort%", resources.getString(errorResourceIDs.first));
substitutionMap.put("%messageLong%", resources.getString(errorResourceIDs.second, desiredURL));

substitutionMap.put("%css%", cssString);

final String errorPage = HtmlLoader.loadResourceFile(webView.getContext(), R.raw.errorpage, substitutionMap);

// We could load the raw html file directly into the webview using a file:///android_res/
// URI - however we'd then need to do some JS hacking to do our String substitutions. Moreover
// we'd have to deal with the mixed-content issues detailed above in that case.
webView.loadDataWithBaseURL(desiredURL, errorPage, "text/html", "UTF8", desiredURL);
return HtmlLoader.loadResourceFile(context, R.raw.errorpage, substitutionMap);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,27 @@
package org.mozilla.focus.engine

import android.content.Context
import android.webkit.WebViewClient
import mozilla.components.concept.engine.EngineSession
import mozilla.components.concept.engine.request.RequestInterceptor
import org.mozilla.focus.browser.BrowserFragment
import org.mozilla.focus.browser.ErrorPage
import org.mozilla.focus.browser.LocalizedContent

const val ERROR_PROTOCOL = "error:"

/**
* [RequestInterceptor] implementation to inject custom content for firefox:* pages.
*/
class CustomContentRequestInterceptor(
private val context: Context
) : RequestInterceptor {

private var currentPageURL = ""

override fun onLoadRequest(session: EngineSession, uri: String): RequestInterceptor.InterceptionResponse? {
currentPageURL = uri

return when (uri) {
BrowserFragment.APP_URL_HOME -> RequestInterceptor.InterceptionResponse("<html></html>")

Expand All @@ -26,4 +35,45 @@ class CustomContentRequestInterceptor(
else -> null
}
}

@Suppress("NestedBlockDepth")
override fun onErrorRequest(session: EngineSession, errorCode: Int, uri: String?) {
uri?.let {
// This is a hack: onReceivedError(WebView, WebResourceRequest, WebResourceError) is API 23+ only,
// - the WebResourceRequest would let us know if the error affects the main frame or not. As a workaround
// we just check whether the failing URL is the current URL, which is enough to detect an error
// in the main frame.

// WebView swallows odd pages and only sends an error (i.e. it doesn't go through the usual
// shouldOverrideUrlLoading), so we need to handle special pages here:
// about: urls are even more odd: webview doesn't tell us _anything_, hence the use of
// a different prefix:
if (it.startsWith(ERROR_PROTOCOL)) {
// format: error:<error_code>
val errorCodePosition = ERROR_PROTOCOL.length
val errorCodeString = it.substring(errorCodePosition)

var desiredErrorCode: Int
try {
desiredErrorCode = Integer.parseInt(errorCodeString)

if (!ErrorPage.supportsErrorCode(desiredErrorCode)) {
// I don't think there's any good way of showing an error if there's an error
// in requesting an error page?
desiredErrorCode = WebViewClient.ERROR_BAD_URL
}
} catch (e: NumberFormatException) {
desiredErrorCode = WebViewClient.ERROR_BAD_URL
}
val errorPageContent = ErrorPage.loadErrorPage(context, it, desiredErrorCode)
session.loadData(errorPageContent)
}
// The API 23+ version also return a *slightly* more usable description, via WebResourceError.getError();
// e.g.. "There was a network error.", whereas this version provides things like "net::ERR_NAME_NOT_RESOLVED"
else if (it == currentPageURL && ErrorPage.supportsErrorCode(errorCode)) {
val errorPageContent = ErrorPage.loadErrorPage(context, currentPageURL, errorCode)
session.loadData(errorPageContent)
}
}
}
}

0 comments on commit 0e498af

Please sign in to comment.