Update fullsdk to 4575844

/google/data/ro/projects/android/fetch_artifact \
    --bid 4575844 \
    --target sdk_phone_x86_64-sdk \
    sdk-repo-linux-sources-4575844.zip

Test: TreeHugger
Change-Id: I81e0eb157b4ac3b38408d0ef86f9d6286471f87a
diff --git a/android/webkit/FindAddress.java b/android/webkit/FindAddress.java
new file mode 100644
index 0000000..31b2427
--- /dev/null
+++ b/android/webkit/FindAddress.java
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed 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 android.webkit;
+
+import java.util.Locale;
+import java.util.regex.MatchResult;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Java implementation of legacy WebView.findAddress algorithm.
+ *
+ * @hide
+ */
+class FindAddress {
+    static class ZipRange {
+        int mLow;
+        int mHigh;
+        int mException1;
+        int mException2;
+        ZipRange(int low, int high, int exception1, int exception2) {
+            mLow = low;
+            mHigh = high;
+            mException1 = exception1;
+            mException2 = exception1;
+        }
+        boolean matches(String zipCode) {
+            int prefix = Integer.parseInt(zipCode.substring(0, 2));
+            return (mLow <= prefix && prefix <= mHigh) || prefix == mException1
+                    || prefix == mException2;
+        }
+    }
+
+    // Addresses consist of at least this many words, not including state and zip code.
+    private static final int MIN_ADDRESS_WORDS = 4;
+
+    // Adddresses consist of at most this many words, not including state and zip code.
+    private static final int MAX_ADDRESS_WORDS = 14;
+
+    // Addresses consist of at most this many lines.
+    private static final int MAX_ADDRESS_LINES = 5;
+
+    // No words in an address are longer than this many characters.
+    private static final int kMaxAddressNameWordLength = 25;
+
+    // Location name should be in the first MAX_LOCATION_NAME_DISTANCE words
+    private static final int MAX_LOCATION_NAME_DISTANCE = 5;
+
+    private static final ZipRange[] sStateZipCodeRanges = {
+            new ZipRange(99, 99, -1, -1), // AK Alaska.
+            new ZipRange(35, 36, -1, -1), // AL Alabama.
+            new ZipRange(71, 72, -1, -1), // AR Arkansas.
+            new ZipRange(96, 96, -1, -1), // AS American Samoa.
+            new ZipRange(85, 86, -1, -1), // AZ Arizona.
+            new ZipRange(90, 96, -1, -1), // CA California.
+            new ZipRange(80, 81, -1, -1), // CO Colorado.
+            new ZipRange(6, 6, -1, -1), // CT Connecticut.
+            new ZipRange(20, 20, -1, -1), // DC District of Columbia.
+            new ZipRange(19, 19, -1, -1), // DE Delaware.
+            new ZipRange(32, 34, -1, -1), // FL Florida.
+            new ZipRange(96, 96, -1, -1), // FM Federated States of Micronesia.
+            new ZipRange(30, 31, -1, -1), // GA Georgia.
+            new ZipRange(96, 96, -1, -1), // GU Guam.
+            new ZipRange(96, 96, -1, -1), // HI Hawaii.
+            new ZipRange(50, 52, -1, -1), // IA Iowa.
+            new ZipRange(83, 83, -1, -1), // ID Idaho.
+            new ZipRange(60, 62, -1, -1), // IL Illinois.
+            new ZipRange(46, 47, -1, -1), // IN Indiana.
+            new ZipRange(66, 67, 73, -1), // KS Kansas.
+            new ZipRange(40, 42, -1, -1), // KY Kentucky.
+            new ZipRange(70, 71, -1, -1), // LA Louisiana.
+            new ZipRange(1, 2, -1, -1), // MA Massachusetts.
+            new ZipRange(20, 21, -1, -1), // MD Maryland.
+            new ZipRange(3, 4, -1, -1), // ME Maine.
+            new ZipRange(96, 96, -1, -1), // MH Marshall Islands.
+            new ZipRange(48, 49, -1, -1), // MI Michigan.
+            new ZipRange(55, 56, -1, -1), // MN Minnesota.
+            new ZipRange(63, 65, -1, -1), // MO Missouri.
+            new ZipRange(96, 96, -1, -1), // MP Northern Mariana Islands.
+            new ZipRange(38, 39, -1, -1), // MS Mississippi.
+            new ZipRange(55, 56, -1, -1), // MT Montana.
+            new ZipRange(27, 28, -1, -1), // NC North Carolina.
+            new ZipRange(58, 58, -1, -1), // ND North Dakota.
+            new ZipRange(68, 69, -1, -1), // NE Nebraska.
+            new ZipRange(3, 4, -1, -1), // NH New Hampshire.
+            new ZipRange(7, 8, -1, -1), // NJ New Jersey.
+            new ZipRange(87, 88, 86, -1), // NM New Mexico.
+            new ZipRange(88, 89, 96, -1), // NV Nevada.
+            new ZipRange(10, 14, 0, 6), // NY New York.
+            new ZipRange(43, 45, -1, -1), // OH Ohio.
+            new ZipRange(73, 74, -1, -1), // OK Oklahoma.
+            new ZipRange(97, 97, -1, -1), // OR Oregon.
+            new ZipRange(15, 19, -1, -1), // PA Pennsylvania.
+            new ZipRange(6, 6, 0, 9), // PR Puerto Rico.
+            new ZipRange(96, 96, -1, -1), // PW Palau.
+            new ZipRange(2, 2, -1, -1), // RI Rhode Island.
+            new ZipRange(29, 29, -1, -1), // SC South Carolina.
+            new ZipRange(57, 57, -1, -1), // SD South Dakota.
+            new ZipRange(37, 38, -1, -1), // TN Tennessee.
+            new ZipRange(75, 79, 87, 88), // TX Texas.
+            new ZipRange(84, 84, -1, -1), // UT Utah.
+            new ZipRange(22, 24, 20, -1), // VA Virginia.
+            new ZipRange(6, 9, -1, -1), // VI Virgin Islands.
+            new ZipRange(5, 5, -1, -1), // VT Vermont.
+            new ZipRange(98, 99, -1, -1), // WA Washington.
+            new ZipRange(53, 54, -1, -1), // WI Wisconsin.
+            new ZipRange(24, 26, -1, -1), // WV West Virginia.
+            new ZipRange(82, 83, -1, -1) // WY Wyoming.
+    };
+
+    // Newlines
+    private static final String NL = "\n\u000B\u000C\r\u0085\u2028\u2029";
+
+    // Space characters
+    private static final String SP = "\u0009\u0020\u00A0\u1680\u2000\u2001"
+            + "\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F"
+            + "\u205F\u3000";
+
+    // Whitespace
+    private static final String WS = SP + NL;
+
+    // Characters that are considered word delimiters.
+    private static final String WORD_DELIM = ",*\u2022" + WS;
+
+    // Lookahead for word end.
+    private static final String WORD_END = "(?=[" + WORD_DELIM + "]|$)";
+
+    // Address words are a sequence of non-delimiter characters.
+    private static final Pattern sWordRe =
+            Pattern.compile("[^" + WORD_DELIM + "]+" + WORD_END, Pattern.CASE_INSENSITIVE);
+
+    // Characters that are considered suffix delimiters for house numbers.
+    private static final String HOUSE_POST_DELIM = ",\"'" + WS;
+
+    // Lookahead for house end.
+    private static final String HOUSE_END = "(?=[" + HOUSE_POST_DELIM + "]|$)";
+
+    // Characters that are considered prefix delimiters for house numbers.
+    private static final String HOUSE_PRE_DELIM = ":" + HOUSE_POST_DELIM;
+
+    // A house number component is "one" or a number, optionally
+    // followed by a single alphabetic character, or
+    private static final String HOUSE_COMPONENT = "(?:one|\\d+([a-z](?=[^a-z]|$)|st|nd|rd|th)?)";
+
+    // House numbers are a repetition of |HOUSE_COMPONENT|, separated by -, and followed by
+    // a delimiter character.
+    private static final Pattern sHouseNumberRe =
+            Pattern.compile(HOUSE_COMPONENT + "(?:-" + HOUSE_COMPONENT + ")*" + HOUSE_END,
+                    Pattern.CASE_INSENSITIVE);
+
+    // XXX: do we want to accept whitespace other than 0x20 in state names?
+    private static final Pattern sStateRe = Pattern.compile("(?:"
+                    + "(ak|alaska)|"
+                    + "(al|alabama)|"
+                    + "(ar|arkansas)|"
+                    + "(as|american[" + SP + "]+samoa)|"
+                    + "(az|arizona)|"
+                    + "(ca|california)|"
+                    + "(co|colorado)|"
+                    + "(ct|connecticut)|"
+                    + "(dc|district[" + SP + "]+of[" + SP + "]+columbia)|"
+                    + "(de|delaware)|"
+                    + "(fl|florida)|"
+                    + "(fm|federated[" + SP + "]+states[" + SP + "]+of[" + SP + "]+micronesia)|"
+                    + "(ga|georgia)|"
+                    + "(gu|guam)|"
+                    + "(hi|hawaii)|"
+                    + "(ia|iowa)|"
+                    + "(id|idaho)|"
+                    + "(il|illinois)|"
+                    + "(in|indiana)|"
+                    + "(ks|kansas)|"
+                    + "(ky|kentucky)|"
+                    + "(la|louisiana)|"
+                    + "(ma|massachusetts)|"
+                    + "(md|maryland)|"
+                    + "(me|maine)|"
+                    + "(mh|marshall[" + SP + "]+islands)|"
+                    + "(mi|michigan)|"
+                    + "(mn|minnesota)|"
+                    + "(mo|missouri)|"
+                    + "(mp|northern[" + SP + "]+mariana[" + SP + "]+islands)|"
+                    + "(ms|mississippi)|"
+                    + "(mt|montana)|"
+                    + "(nc|north[" + SP + "]+carolina)|"
+                    + "(nd|north[" + SP + "]+dakota)|"
+                    + "(ne|nebraska)|"
+                    + "(nh|new[" + SP + "]+hampshire)|"
+                    + "(nj|new[" + SP + "]+jersey)|"
+                    + "(nm|new[" + SP + "]+mexico)|"
+                    + "(nv|nevada)|"
+                    + "(ny|new[" + SP + "]+york)|"
+                    + "(oh|ohio)|"
+                    + "(ok|oklahoma)|"
+                    + "(or|oregon)|"
+                    + "(pa|pennsylvania)|"
+                    + "(pr|puerto[" + SP + "]+rico)|"
+                    + "(pw|palau)|"
+                    + "(ri|rhode[" + SP + "]+island)|"
+                    + "(sc|south[" + SP + "]+carolina)|"
+                    + "(sd|south[" + SP + "]+dakota)|"
+                    + "(tn|tennessee)|"
+                    + "(tx|texas)|"
+                    + "(ut|utah)|"
+                    + "(va|virginia)|"
+                    + "(vi|virgin[" + SP + "]+islands)|"
+                    + "(vt|vermont)|"
+                    + "(wa|washington)|"
+                    + "(wi|wisconsin)|"
+                    + "(wv|west[" + SP + "]+virginia)|"
+                    + "(wy|wyoming)"
+                    + ")" + WORD_END,
+            Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern sLocationNameRe = Pattern.compile("(?:"
+                    + "alley|annex|arcade|ave[.]?|avenue|alameda|bayou|"
+                    + "beach|bend|bluffs?|bottom|boulevard|branch|bridge|"
+                    + "brooks?|burgs?|bypass|broadway|camino|camp|canyon|"
+                    + "cape|causeway|centers?|circles?|cliffs?|club|common|"
+                    + "corners?|course|courts?|coves?|creek|crescent|crest|"
+                    + "crossing|crossroad|curve|circulo|dale|dam|divide|"
+                    + "drives?|estates?|expressway|extensions?|falls?|ferry|"
+                    + "fields?|flats?|fords?|forest|forges?|forks?|fort|"
+                    + "freeway|gardens?|gateway|glens?|greens?|groves?|"
+                    + "harbors?|haven|heights|highway|hills?|hollow|inlet|"
+                    + "islands?|isle|junctions?|keys?|knolls?|lakes?|land|"
+                    + "landing|lane|lights?|loaf|locks?|lodge|loop|mall|"
+                    + "manors?|meadows?|mews|mills?|mission|motorway|mount|"
+                    + "mountains?|neck|orchard|oval|overpass|parks?|"
+                    + "parkways?|pass|passage|path|pike|pines?|plains?|"
+                    + "plaza|points?|ports?|prairie|privada|radial|ramp|"
+                    + "ranch|rapids?|rd[.]?|rest|ridges?|river|roads?|route|"
+                    + "row|rue|run|shoals?|shores?|skyway|springs?|spurs?|"
+                    + "squares?|station|stravenue|stream|st[.]?|streets?|"
+                    + "summit|speedway|terrace|throughway|trace|track|"
+                    + "trafficway|trail|tunnel|turnpike|underpass|unions?|"
+                    + "valleys?|viaduct|views?|villages?|ville|vista|walks?|"
+                    + "wall|ways?|wells?|xing|xrd)" + WORD_END,
+            Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern sSuffixedNumberRe =
+            Pattern.compile("(\\d+)(st|nd|rd|th)", Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern sZipCodeRe =
+            Pattern.compile("(?:\\d{5}(?:-\\d{4})?)" + WORD_END, Pattern.CASE_INSENSITIVE);
+
+    private static boolean checkHouseNumber(String houseNumber) {
+        // Make sure that there are at most 5 digits.
+        int digitCount = 0;
+        for (int i = 0; i < houseNumber.length(); ++i) {
+            if (Character.isDigit(houseNumber.charAt(i))) ++digitCount;
+        }
+        if (digitCount > 5) return false;
+
+        // Make sure that any ordinals are valid.
+        Matcher suffixMatcher = sSuffixedNumberRe.matcher(houseNumber);
+        while (suffixMatcher.find()) {
+            int num = Integer.parseInt(suffixMatcher.group(1));
+            if (num == 0) {
+                return false; // 0th is invalid.
+            }
+            String suffix = suffixMatcher.group(2).toLowerCase(Locale.getDefault());
+            switch (num % 10) {
+                case 1:
+                    return suffix.equals(num % 100 == 11 ? "th" : "st");
+                case 2:
+                    return suffix.equals(num % 100 == 12 ? "th" : "nd");
+                case 3:
+                    return suffix.equals(num % 100 == 13 ? "th" : "rd");
+                default:
+                    return suffix.equals("th");
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Attempt to match a house number beginnning at position offset
+     * in content.  The house number must be followed by a word
+     * delimiter or the end of the string, and if offset is non-zero,
+     * then it must also be preceded by a word delimiter.
+     *
+     * @return a MatchResult if a valid house number was found.
+     */
+    private static MatchResult matchHouseNumber(String content, int offset) {
+        if (offset > 0 && HOUSE_PRE_DELIM.indexOf(content.charAt(offset - 1)) == -1) return null;
+        Matcher matcher = sHouseNumberRe.matcher(content).region(offset, content.length());
+        if (matcher.lookingAt()) {
+            MatchResult matchResult = matcher.toMatchResult();
+            if (checkHouseNumber(matchResult.group(0))) return matchResult;
+        }
+        return null;
+    }
+
+    /**
+     * Attempt to match a US state beginnning at position offset in
+     * content.  The matching state must be followed by a word
+     * delimiter or the end of the string, and if offset is non-zero,
+     * then it must also be preceded by a word delimiter.
+     *
+     * @return a MatchResult if a valid US state (or two letter code)
+     * was found.
+     */
+    private static MatchResult matchState(String content, int offset) {
+        if (offset > 0 && WORD_DELIM.indexOf(content.charAt(offset - 1)) == -1) return null;
+        Matcher stateMatcher = sStateRe.matcher(content).region(offset, content.length());
+        return stateMatcher.lookingAt() ? stateMatcher.toMatchResult() : null;
+    }
+
+    /**
+     * Test whether zipCode matches the U.S. zip code format (ddddd or
+     * ddddd-dddd) and is within the expected range, given that
+     * stateMatch is a match of sStateRe.
+     *
+     * @return true if zipCode is a valid zip code, is legal for the
+     * matched state, and is followed by a word delimiter or the end
+     * of the string.
+     */
+    private static boolean isValidZipCode(String zipCode, MatchResult stateMatch) {
+        if (stateMatch == null) return false;
+        // Work out the index of the state, based on which group matched.
+        int stateIndex = stateMatch.groupCount();
+        while (stateIndex > 0) {
+            if (stateMatch.group(stateIndex--) != null) break;
+        }
+        return sZipCodeRe.matcher(zipCode).matches()
+                && sStateZipCodeRanges[stateIndex].matches(zipCode);
+    }
+
+    /**
+     * Test whether location is one of the valid locations.
+     *
+     * @return true if location starts with a valid location name
+     * followed by a word delimiter or the end of the string.
+     */
+    private static boolean isValidLocationName(String location) {
+        return sLocationNameRe.matcher(location).matches();
+    }
+
+    /**
+     * Attempt to match a complete address in content, starting with
+     * houseNumberMatch.
+     *
+     * @param content The string to search.
+     * @param houseNumberMatch A matching house number to start extending.
+     * @return +ve: the end of the match
+     *         +ve: the position to restart searching for house numbers, negated.
+     */
+    private static int attemptMatch(String content, MatchResult houseNumberMatch) {
+        int restartPos = -1;
+        int nonZipMatch = -1;
+        int it = houseNumberMatch.end();
+        int numLines = 1;
+        boolean consecutiveHouseNumbers = true;
+        boolean foundLocationName = false;
+        int wordCount = 1;
+        String lastWord = "";
+
+        Matcher matcher = sWordRe.matcher(content);
+
+        for (; it < content.length(); lastWord = matcher.group(0), it = matcher.end()) {
+            if (!matcher.find(it)) {
+                // No more words in the input sequence.
+                return -content.length();
+            }
+            if (matcher.end() - matcher.start() > kMaxAddressNameWordLength) {
+                // Word is too long to be part of an address. Fail.
+                return -matcher.end();
+            }
+
+            // Count the number of newlines we just consumed.
+            while (it < matcher.start()) {
+                if (NL.indexOf(content.charAt(it++)) != -1) ++numLines;
+            }
+
+            // Consumed too many lines. Fail.
+            if (numLines > MAX_ADDRESS_LINES) break;
+
+            // Consumed too many words. Fail.
+            if (++wordCount > MAX_ADDRESS_WORDS) break;
+
+            if (matchHouseNumber(content, it) != null) {
+                if (consecutiveHouseNumbers && numLines > 1) {
+                    // Last line ended with a number, and this this line starts with one.
+                    // Restart at this number.
+                    return -it;
+                }
+                // Remember the position of this match as the restart position.
+                if (restartPos == -1) restartPos = it;
+                continue;
+            }
+
+            consecutiveHouseNumbers = false;
+
+            if (isValidLocationName(matcher.group(0))) {
+                foundLocationName = true;
+                continue;
+            }
+
+            if (wordCount == MAX_LOCATION_NAME_DISTANCE && !foundLocationName) {
+                // Didn't find a location name in time. Fail.
+                it = matcher.end();
+                break;
+            }
+
+            if (foundLocationName && wordCount > MIN_ADDRESS_WORDS) {
+                // We can now attempt to match a state.
+                MatchResult stateMatch = matchState(content, it);
+                if (stateMatch != null) {
+                    if (lastWord.equals("et") && stateMatch.group(0).equals("al")) {
+                        // Reject "et al" as a false postitive.
+                        it = stateMatch.end();
+                        break;
+                    }
+
+                    // At this point we've matched a state; try to match a zip code after it.
+                    Matcher zipMatcher = sWordRe.matcher(content);
+                    if (zipMatcher.find(stateMatch.end())
+                            && isValidZipCode(zipMatcher.group(0), stateMatch)) {
+                        return zipMatcher.end();
+                    }
+                    // The content ends with a state but no zip
+                    // code. This is a legal match according to the
+                    // documentation. N.B. This differs from the
+                    // original c++ implementation, which only allowed
+                    // the zip code to be optional at the end of the
+                    // string, which presumably is a bug.  Now we
+                    // prefer to find a match with a zip code, but
+                    // remember non-zip matches and return them if
+                    // necessary.
+                    nonZipMatch = stateMatch.end();
+                }
+            }
+        }
+
+        if (nonZipMatch > 0) return nonZipMatch;
+
+        return -(restartPos > 0 ? restartPos : it);
+    }
+
+    /**
+     * Return the first matching address in content.
+     *
+     * @param content The string to search.
+     * @return The first valid address, or null if no address was matched.
+     */
+    static String findAddress(String content) {
+        Matcher houseNumberMatcher = sHouseNumberRe.matcher(content);
+        int start = 0;
+        while (houseNumberMatcher.find(start)) {
+            if (checkHouseNumber(houseNumberMatcher.group(0))) {
+                start = houseNumberMatcher.start();
+                int end = attemptMatch(content, houseNumberMatcher);
+                if (end > 0) {
+                    return content.substring(start, end);
+                }
+                start = -end;
+            } else {
+                start = houseNumberMatcher.end();
+            }
+        }
+        return null;
+    }
+}
diff --git a/android/webkit/SafeBrowsingResponse.java b/android/webkit/SafeBrowsingResponse.java
index 960b56b..1d3a617 100644
--- a/android/webkit/SafeBrowsingResponse.java
+++ b/android/webkit/SafeBrowsingResponse.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,5 +16,36 @@
 
 package android.webkit;
 
-public class SafeBrowsingResponse {
+/**
+ * Used to indicate an action to take when hitting a malicious URL. Instances of this class are
+ * created by the WebView and passed to {@link android.webkit.WebViewClient#onSafeBrowsingHit}. The
+ * host application must call {@link #showInterstitial(boolean)}, {@link #proceed(boolean)}, or
+ * {@link #backToSafety(boolean)} to set the WebView's response to the Safe Browsing hit.
+ *
+ * <p>
+ * If reporting is enabled, all reports will be sent according to the privacy policy referenced by
+ * {@link android.webkit.WebView#getSafeBrowsingPrivacyPolicyUrl()}.
+ */
+public abstract class SafeBrowsingResponse {
+
+    /**
+     * Display the default interstitial.
+     *
+     * @param allowReporting {@code true} if the interstitial should show a reporting checkbox.
+     */
+    public abstract void showInterstitial(boolean allowReporting);
+
+    /**
+     * Act as if the user clicked "visit this unsafe site."
+     *
+     * @param report {@code true} to enable Safe Browsing reporting.
+     */
+    public abstract void proceed(boolean report);
+
+    /**
+     * Act as if the user clicked "back to safety."
+     *
+     * @param report {@code true} to enable Safe Browsing reporting.
+     */
+    public abstract void backToSafety(boolean report);
 }
diff --git a/android/webkit/WebViewClient.java b/android/webkit/WebViewClient.java
index f5d220c..d0f9eee 100644
--- a/android/webkit/WebViewClient.java
+++ b/android/webkit/WebViewClient.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2008 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,545 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.webkit;
 
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.graphics.Bitmap;
+import android.net.http.SslError;
+import android.os.Message;
+import android.view.InputEvent;
+import android.view.KeyEvent;
+import android.view.ViewRootImpl;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 public class WebViewClient {
+
+    /**
+     * Give the host application a chance to take over the control when a new
+     * url is about to be loaded in the current WebView. If WebViewClient is not
+     * provided, by default WebView will ask Activity Manager to choose the
+     * proper handler for the url. If WebViewClient is provided, return {@code true}
+     * means the host application handles the url, while return {@code false} means the
+     * current WebView handles the url.
+     * This method is not called for requests using the POST "method".
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param url The url to be loaded.
+     * @return {@code true} if the host application wants to leave the current WebView
+     *         and handle the url itself, otherwise return {@code false}.
+     * @deprecated Use {@link #shouldOverrideUrlLoading(WebView, WebResourceRequest)
+     *             shouldOverrideUrlLoading(WebView, WebResourceRequest)} instead.
+     */
+    @Deprecated
+    public boolean shouldOverrideUrlLoading(WebView view, String url) {
+        return false;
+    }
+
+    /**
+     * Give the host application a chance to take over the control when a new
+     * url is about to be loaded in the current WebView. If WebViewClient is not
+     * provided, by default WebView will ask Activity Manager to choose the
+     * proper handler for the url. If WebViewClient is provided, return {@code true}
+     * means the host application handles the url, while return {@code false} means the
+     * current WebView handles the url.
+     *
+     * <p>Notes:
+     * <ul>
+     * <li>This method is not called for requests using the POST &quot;method&quot;.</li>
+     * <li>This method is also called for subframes with non-http schemes, thus it is
+     * strongly disadvised to unconditionally call {@link WebView#loadUrl(String)}
+     * with the request's url from inside the method and then return {@code true},
+     * as this will make WebView to attempt loading a non-http url, and thus fail.</li>
+     * </ul>
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param request Object containing the details of the request.
+     * @return {@code true} if the host application wants to leave the current WebView
+     *         and handle the url itself, otherwise return {@code false}.
+     */
+    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
+        return shouldOverrideUrlLoading(view, request.getUrl().toString());
+    }
+
+    /**
+     * Notify the host application that a page has started loading. This method
+     * is called once for each main frame load so a page with iframes or
+     * framesets will call onPageStarted one time for the main frame. This also
+     * means that onPageStarted will not be called when the contents of an
+     * embedded frame changes, i.e. clicking a link whose target is an iframe,
+     * it will also not be called for fragment navigations (navigations to
+     * #fragment_id).
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param url The url to be loaded.
+     * @param favicon The favicon for this page if it already exists in the
+     *            database.
+     */
+    public void onPageStarted(WebView view, String url, Bitmap favicon) {
+    }
+
+    /**
+     * Notify the host application that a page has finished loading. This method
+     * is called only for main frame. When onPageFinished() is called, the
+     * rendering picture may not be updated yet. To get the notification for the
+     * new Picture, use {@link WebView.PictureListener#onNewPicture}.
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param url The url of the page.
+     */
+    public void onPageFinished(WebView view, String url) {
+    }
+
+    /**
+     * Notify the host application that the WebView will load the resource
+     * specified by the given url.
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param url The url of the resource the WebView will load.
+     */
+    public void onLoadResource(WebView view, String url) {
+    }
+
+    /**
+     * Notify the host application that {@link android.webkit.WebView} content left over from
+     * previous page navigations will no longer be drawn.
+     *
+     * <p>This callback can be used to determine the point at which it is safe to make a recycled
+     * {@link android.webkit.WebView} visible, ensuring that no stale content is shown. It is called
+     * at the earliest point at which it can be guaranteed that {@link WebView#onDraw} will no
+     * longer draw any content from previous navigations. The next draw will display either the
+     * {@link WebView#setBackgroundColor background color} of the {@link WebView}, or some of the
+     * contents of the newly loaded page.
+     *
+     * <p>This method is called when the body of the HTTP response has started loading, is reflected
+     * in the DOM, and will be visible in subsequent draws. This callback occurs early in the
+     * document loading process, and as such you should expect that linked resources (for example,
+     * CSS and images) may not be available.
+     *
+     * <p>For more fine-grained notification of visual state updates, see {@link
+     * WebView#postVisualStateCallback}.
+     *
+     * <p>Please note that all the conditions and recommendations applicable to
+     * {@link WebView#postVisualStateCallback} also apply to this API.
+     *
+     * <p>This callback is only called for main frame navigations.
+     *
+     * @param view The {@link android.webkit.WebView} for which the navigation occurred.
+     * @param url  The URL corresponding to the page navigation that triggered this callback.
+     */
+    public void onPageCommitVisible(WebView view, String url) {
+    }
+
+    /**
+     * Notify the host application of a resource request and allow the
+     * application to return the data.  If the return value is {@code null}, the WebView
+     * will continue to load the resource as usual.  Otherwise, the return
+     * response and data will be used.
+     *
+     * <p class="note"><b>Note:</b> This method is called on a thread
+     * other than the UI thread so clients should exercise caution
+     * when accessing private data or the view system.
+     *
+     * <p class="note"><b>Note:</b> When Safe Browsing is enabled, these URLs still undergo Safe
+     * Browsing checks. If this is undesired, whitelist the URL with {@link
+     * WebView#setSafeBrowsingWhitelist} or ignore the warning with {@link #onSafeBrowsingHit}.
+     *
+     * @param view The {@link android.webkit.WebView} that is requesting the
+     *             resource.
+     * @param url The raw url of the resource.
+     * @return A {@link android.webkit.WebResourceResponse} containing the
+     *         response information or {@code null} if the WebView should load the
+     *         resource itself.
+     * @deprecated Use {@link #shouldInterceptRequest(WebView, WebResourceRequest)
+     *             shouldInterceptRequest(WebView, WebResourceRequest)} instead.
+     */
+    @Deprecated
+    @Nullable
+    public WebResourceResponse shouldInterceptRequest(WebView view,
+            String url) {
+        return null;
+    }
+
+    /**
+     * Notify the host application of a resource request and allow the
+     * application to return the data.  If the return value is {@code null}, the WebView
+     * will continue to load the resource as usual.  Otherwise, the return
+     * response and data will be used.
+     *
+     * <p class="note"><b>Note:</b> This method is called on a thread
+     * other than the UI thread so clients should exercise caution
+     * when accessing private data or the view system.
+     *
+     * <p class="note"><b>Note:</b> When Safe Browsing is enabled, these URLs still undergo Safe
+     * Browsing checks. If this is undesired, whitelist the URL with {@link
+     * WebView#setSafeBrowsingWhitelist} or ignore the warning with {@link #onSafeBrowsingHit}.
+     *
+     * @param view The {@link android.webkit.WebView} that is requesting the
+     *             resource.
+     * @param request Object containing the details of the request.
+     * @return A {@link android.webkit.WebResourceResponse} containing the
+     *         response information or {@code null} if the WebView should load the
+     *         resource itself.
+     */
+    @Nullable
+    public WebResourceResponse shouldInterceptRequest(WebView view,
+            WebResourceRequest request) {
+        return shouldInterceptRequest(view, request.getUrl().toString());
+    }
+
+    /**
+     * Notify the host application that there have been an excessive number of
+     * HTTP redirects. As the host application if it would like to continue
+     * trying to load the resource. The default behavior is to send the cancel
+     * message.
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param cancelMsg The message to send if the host wants to cancel
+     * @param continueMsg The message to send if the host wants to continue
+     * @deprecated This method is no longer called. When the WebView encounters
+     *             a redirect loop, it will cancel the load.
+     */
+    @Deprecated
+    public void onTooManyRedirects(WebView view, Message cancelMsg,
+            Message continueMsg) {
+        cancelMsg.sendToTarget();
+    }
+
+    // These ints must match up to the hidden values in EventHandler.
+    /** Generic error */
+    public static final int ERROR_UNKNOWN = -1;
+    /** Server or proxy hostname lookup failed */
+    public static final int ERROR_HOST_LOOKUP = -2;
+    /** Unsupported authentication scheme (not basic or digest) */
+    public static final int ERROR_UNSUPPORTED_AUTH_SCHEME = -3;
+    /** User authentication failed on server */
+    public static final int ERROR_AUTHENTICATION = -4;
+    /** User authentication failed on proxy */
+    public static final int ERROR_PROXY_AUTHENTICATION = -5;
+    /** Failed to connect to the server */
+    public static final int ERROR_CONNECT = -6;
+    /** Failed to read or write to the server */
+    public static final int ERROR_IO = -7;
+    /** Connection timed out */
+    public static final int ERROR_TIMEOUT = -8;
+    /** Too many redirects */
+    public static final int ERROR_REDIRECT_LOOP = -9;
+    /** Unsupported URI scheme */
+    public static final int ERROR_UNSUPPORTED_SCHEME = -10;
+    /** Failed to perform SSL handshake */
+    public static final int ERROR_FAILED_SSL_HANDSHAKE = -11;
+    /** Malformed URL */
+    public static final int ERROR_BAD_URL = -12;
+    /** Generic file error */
+    public static final int ERROR_FILE = -13;
+    /** File not found */
+    public static final int ERROR_FILE_NOT_FOUND = -14;
+    /** Too many requests during this load */
+    public static final int ERROR_TOO_MANY_REQUESTS = -15;
+    /** Resource load was canceled by Safe Browsing */
+    public static final int ERROR_UNSAFE_RESOURCE = -16;
+
+    /** @hide */
+    @IntDef(prefix = { "SAFE_BROWSING_THREAT_" }, value = {
+            SAFE_BROWSING_THREAT_UNKNOWN,
+            SAFE_BROWSING_THREAT_MALWARE,
+            SAFE_BROWSING_THREAT_PHISHING,
+            SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SafeBrowsingThreat {}
+
+    /** The resource was blocked for an unknown reason */
+    public static final int SAFE_BROWSING_THREAT_UNKNOWN = 0;
+    /** The resource was blocked because it contains malware */
+    public static final int SAFE_BROWSING_THREAT_MALWARE = 1;
+    /** The resource was blocked because it contains deceptive content */
+    public static final int SAFE_BROWSING_THREAT_PHISHING = 2;
+    /** The resource was blocked because it contains unwanted software */
+    public static final int SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE = 3;
+
+    /**
+     * Report an error to the host application. These errors are unrecoverable
+     * (i.e. the main resource is unavailable). The {@code errorCode} parameter
+     * corresponds to one of the {@code ERROR_*} constants.
+     * @param view The WebView that is initiating the callback.
+     * @param errorCode The error code corresponding to an ERROR_* value.
+     * @param description A String describing the error.
+     * @param failingUrl The url that failed to load.
+     * @deprecated Use {@link #onReceivedError(WebView, WebResourceRequest, WebResourceError)
+     *             onReceivedError(WebView, WebResourceRequest, WebResourceError)} instead.
+     */
+    @Deprecated
+    public void onReceivedError(WebView view, int errorCode,
+            String description, String failingUrl) {
+    }
+
+    /**
+     * Report web resource loading error to the host application. These errors usually indicate
+     * inability to connect to the server. Note that unlike the deprecated version of the callback,
+     * the new version will be called for any resource (iframe, image, etc.), not just for the main
+     * page. Thus, it is recommended to perform minimum required work in this callback.
+     * @param view The WebView that is initiating the callback.
+     * @param request The originating request.
+     * @param error Information about the error occurred.
+     */
+    public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
+        if (request.isForMainFrame()) {
+            onReceivedError(view,
+                    error.getErrorCode(), error.getDescription().toString(),
+                    request.getUrl().toString());
+        }
+    }
+
+    /**
+     * Notify the host application that an HTTP error has been received from the server while
+     * loading a resource.  HTTP errors have status codes &gt;= 400.  This callback will be called
+     * for any resource (iframe, image, etc.), not just for the main page. Thus, it is recommended
+     * to perform minimum required work in this callback. Note that the content of the server
+     * response may not be provided within the {@code errorResponse} parameter.
+     * @param view The WebView that is initiating the callback.
+     * @param request The originating request.
+     * @param errorResponse Information about the error occurred.
+     */
+    public void onReceivedHttpError(
+            WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
+    }
+
+    /**
+     * As the host application if the browser should resend data as the
+     * requested page was a result of a POST. The default is to not resend the
+     * data.
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param dontResend The message to send if the browser should not resend
+     * @param resend The message to send if the browser should resend data
+     */
+    public void onFormResubmission(WebView view, Message dontResend,
+            Message resend) {
+        dontResend.sendToTarget();
+    }
+
+    /**
+     * Notify the host application to update its visited links database.
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param url The url being visited.
+     * @param isReload {@code true} if this url is being reloaded.
+     */
+    public void doUpdateVisitedHistory(WebView view, String url,
+            boolean isReload) {
+    }
+
+    /**
+     * Notify the host application that an SSL error occurred while loading a
+     * resource. The host application must call either handler.cancel() or
+     * handler.proceed(). Note that the decision may be retained for use in
+     * response to future SSL errors. The default behavior is to cancel the
+     * load.
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param handler An SslErrorHandler object that will handle the user's
+     *            response.
+     * @param error The SSL error object.
+     */
+    public void onReceivedSslError(WebView view, SslErrorHandler handler,
+            SslError error) {
+        handler.cancel();
+    }
+
+    /**
+     * Notify the host application to handle a SSL client certificate request. The host application
+     * is responsible for showing the UI if desired and providing the keys. There are three ways to
+     * respond: {@link ClientCertRequest#proceed}, {@link ClientCertRequest#cancel}, or {@link
+     * ClientCertRequest#ignore}. Webview stores the response in memory (for the life of the
+     * application) if {@link ClientCertRequest#proceed} or {@link ClientCertRequest#cancel} is
+     * called and does not call {@code onReceivedClientCertRequest()} again for the same host and
+     * port pair. Webview does not store the response if {@link ClientCertRequest#ignore}
+     * is called. Note that, multiple layers in chromium network stack might be
+     * caching the responses, so the behavior for ignore is only a best case
+     * effort.
+     *
+     * This method is called on the UI thread. During the callback, the
+     * connection is suspended.
+     *
+     * For most use cases, the application program should implement the
+     * {@link android.security.KeyChainAliasCallback} interface and pass it to
+     * {@link android.security.KeyChain#choosePrivateKeyAlias} to start an
+     * activity for the user to choose the proper alias. The keychain activity will
+     * provide the alias through the callback method in the implemented interface. Next
+     * the application should create an async task to call
+     * {@link android.security.KeyChain#getPrivateKey} to receive the key.
+     *
+     * An example implementation of client certificates can be seen at
+     * <A href="https://android.googlesource.com/platform/packages/apps/Browser/+/android-5.1.1_r1/src/com/android/browser/Tab.java">
+     * AOSP Browser</a>
+     *
+     * The default behavior is to cancel, returning no client certificate.
+     *
+     * @param view The WebView that is initiating the callback
+     * @param request An instance of a {@link ClientCertRequest}
+     *
+     */
+    public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
+        request.cancel();
+    }
+
+    /**
+     * Notifies the host application that the WebView received an HTTP
+     * authentication request. The host application can use the supplied
+     * {@link HttpAuthHandler} to set the WebView's response to the request.
+     * The default behavior is to cancel the request.
+     *
+     * @param view the WebView that is initiating the callback
+     * @param handler the HttpAuthHandler used to set the WebView's response
+     * @param host the host requiring authentication
+     * @param realm the realm for which authentication is required
+     * @see WebView#getHttpAuthUsernamePassword
+     */
+    public void onReceivedHttpAuthRequest(WebView view,
+            HttpAuthHandler handler, String host, String realm) {
+        handler.cancel();
+    }
+
+    /**
+     * Give the host application a chance to handle the key event synchronously.
+     * e.g. menu shortcut key events need to be filtered this way. If return
+     * true, WebView will not handle the key event. If return {@code false}, WebView
+     * will always handle the key event, so none of the super in the view chain
+     * will see the key event. The default behavior returns {@code false}.
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param event The key event.
+     * @return {@code true} if the host application wants to handle the key event
+     *         itself, otherwise return {@code false}
+     */
+    public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
+        return false;
+    }
+
+    /**
+     * Notify the host application that a key was not handled by the WebView.
+     * Except system keys, WebView always consumes the keys in the normal flow
+     * or if {@link #shouldOverrideKeyEvent} returns {@code true}. This is called asynchronously
+     * from where the key is dispatched. It gives the host application a chance
+     * to handle the unhandled key events.
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param event The key event.
+     */
+    public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
+        onUnhandledInputEventInternal(view, event);
+    }
+
+    /**
+     * Notify the host application that a input event was not handled by the WebView.
+     * Except system keys, WebView always consumes input events in the normal flow
+     * or if {@link #shouldOverrideKeyEvent} returns {@code true}. This is called asynchronously
+     * from where the event is dispatched. It gives the host application a chance
+     * to handle the unhandled input events.
+     *
+     * Note that if the event is a {@link android.view.MotionEvent}, then it's lifetime is only
+     * that of the function call. If the WebViewClient wishes to use the event beyond that, then it
+     * <i>must</i> create a copy of the event.
+     *
+     * It is the responsibility of overriders of this method to call
+     * {@link #onUnhandledKeyEvent(WebView, KeyEvent)}
+     * when appropriate if they wish to continue receiving events through it.
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param event The input event.
+     * @removed
+     */
+    public void onUnhandledInputEvent(WebView view, InputEvent event) {
+        if (event instanceof KeyEvent) {
+            onUnhandledKeyEvent(view, (KeyEvent) event);
+            return;
+        }
+        onUnhandledInputEventInternal(view, event);
+    }
+
+    private void onUnhandledInputEventInternal(WebView view, InputEvent event) {
+        ViewRootImpl root = view.getViewRootImpl();
+        if (root != null) {
+            root.dispatchUnhandledInputEvent(event);
+        }
+    }
+
+    /**
+     * Notify the host application that the scale applied to the WebView has
+     * changed.
+     *
+     * @param view The WebView that is initiating the callback.
+     * @param oldScale The old scale factor
+     * @param newScale The new scale factor
+     */
+    public void onScaleChanged(WebView view, float oldScale, float newScale) {
+    }
+
+    /**
+     * Notify the host application that a request to automatically log in the
+     * user has been processed.
+     * @param view The WebView requesting the login.
+     * @param realm The account realm used to look up accounts.
+     * @param account An optional account. If not {@code null}, the account should be
+     *                checked against accounts on the device. If it is a valid
+     *                account, it should be used to log in the user.
+     * @param args Authenticator specific arguments used to log in the user.
+     */
+    public void onReceivedLoginRequest(WebView view, String realm,
+            @Nullable String account, String args) {
+    }
+
+    /**
+     * Notify host application that the given WebView's render process has exited.
+     *
+     * Multiple WebView instances may be associated with a single render process;
+     * onRenderProcessGone will be called for each WebView that was affected.
+     * The application's implementation of this callback should only attempt to
+     * clean up the specific WebView given as a parameter, and should not assume
+     * that other WebView instances are affected.
+     *
+     * The given WebView can't be used, and should be removed from the view hierarchy,
+     * all references to it should be cleaned up, e.g any references in the Activity
+     * or other classes saved using {@link android.view.View#findViewById} and similar calls, etc.
+     *
+     * To cause an render process crash for test purpose, the application can
+     * call {@code loadUrl("chrome://crash")} on the WebView. Note that multiple WebView
+     * instances may be affected if they share a render process, not just the
+     * specific WebView which loaded chrome://crash.
+     *
+     * @param view The WebView which needs to be cleaned up.
+     * @param detail the reason why it exited.
+     * @return {@code true} if the host application handled the situation that process has
+     *         exited, otherwise, application will crash if render process crashed,
+     *         or be killed if render process was killed by the system.
+     */
+    public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) {
+        return false;
+    }
+
+    /**
+     * Notify the host application that a loading URL has been flagged by Safe Browsing.
+     *
+     * The application must invoke the callback to indicate the preferred response. The default
+     * behavior is to show an interstitial to the user, with the reporting checkbox visible.
+     *
+     * If the application needs to show its own custom interstitial UI, the callback can be invoked
+     * asynchronously with {@link SafeBrowsingResponse#backToSafety} or {@link
+     * SafeBrowsingResponse#proceed}, depending on user response.
+     *
+     * @param view The WebView that hit the malicious resource.
+     * @param request Object containing the details of the request.
+     * @param threatType The reason the resource was caught by Safe Browsing, corresponding to a
+     *                   {@code SAFE_BROWSING_THREAT_*} value.
+     * @param callback Applications must invoke one of the callback methods.
+     */
+    public void onSafeBrowsingHit(WebView view, WebResourceRequest request,
+            @SafeBrowsingThreat int threatType, SafeBrowsingResponse callback) {
+        callback.showInterstitial(/* allowReporting */ true);
+    }
 }
diff --git a/android/webkit/WebViewFactory.java b/android/webkit/WebViewFactory.java
index b3522ec..e9fe481 100644
--- a/android/webkit/WebViewFactory.java
+++ b/android/webkit/WebViewFactory.java
@@ -27,7 +27,6 @@
 import android.content.pm.Signature;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.StrictMode;
 import android.os.Trace;
 import android.util.AndroidRuntimeException;
 import android.util.ArraySet;
@@ -251,7 +250,6 @@
                         "WebView.disableWebView() was called: WebView is disabled");
             }
 
-            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
             Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getProvider()");
             try {
                 Class<WebViewFactoryProvider> providerClass = getProviderClass();
@@ -279,7 +277,6 @@
                 }
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
-                StrictMode.setThreadPolicy(oldPolicy);
             }
         }
     }
diff --git a/android/webkit/WebViewFactoryProvider.java b/android/webkit/WebViewFactoryProvider.java
index 3ced6a5..4f7cdab 100644
--- a/android/webkit/WebViewFactoryProvider.java
+++ b/android/webkit/WebViewFactoryProvider.java
@@ -172,4 +172,10 @@
      * @return the singleton WebViewDatabase instance
      */
     WebViewDatabase getWebViewDatabase(Context context);
+
+    /**
+     * Gets the classloader used to load internal WebView implementation classes. This interface
+     * should only be used by the WebView Support Library.
+     */
+    ClassLoader getWebViewClassLoader();
 }