Back-port: "[Android WebView] Synthesize a fake page loading event on page source modification (Re-land)"

Back-port of https://codereview.chromium.org/970883002/ for m40.

Original description:

    [Android WebView] Synthesize a fake page loading event on page source modification (Re-land)

    When a script modifies page source of a non-committed page, we need to
    notify clients, so they can update the URL bar to avoid confusion.

    New logic since the last attempt (https://codereview.chromium.org/924833003/):
    distinguish between a "vanilla" WebView state (basically, a newly created
    WebView, where no loading attempts have been made) and an "attempted to
    navigate" state. In the "vanilla" state, don't fire synthesized page loading
    events to avoid confusing clients. This is safe, as WebView is guaranteed to be
    on a blank page.

    Implementation note: we detect navigation attempts using
    didStartProvisionalLoadForFrame WebContentsObserver event on the Java side. As
    for popups AwWebContentsObserver gets re-attached from the original popup
    WebView to the one provided by the client, notifications issued inbetween can be
    missed on the Java side. To work around this, we assume that WebViews opened as
    popups can never be in "vanilla" state (as they are anyway opened as a result of
    navigation).

    BUG=458569, 462213
    TBR=davidben@chromium.org,tedchoc@chromium.org

Bug: 19325392
Change-Id: I3df0484f00d2b816cb0293bec432b2fa6ac5e05b
diff --git a/GypAndroid.darwin-arm.mk b/GypAndroid.darwin-arm.mk
index 51f4142..1c031ac 100644
--- a/GypAndroid.darwin-arm.mk
+++ b/GypAndroid.darwin-arm.mk
@@ -81,6 +81,7 @@
 include $(LOCAL_PATH)/content/content_strings_grd.target.darwin-arm.mk
 include $(LOCAL_PATH)/content/content_utility.target.darwin-arm.mk
 include $(LOCAL_PATH)/content/gesture_event_type_java.target.darwin-arm.mk
+include $(LOCAL_PATH)/content/invalidate_types_java.target.darwin-arm.mk
 include $(LOCAL_PATH)/content/java_set_jni_headers.target.darwin-arm.mk
 include $(LOCAL_PATH)/content/motionevent_jni_headers.target.darwin-arm.mk
 include $(LOCAL_PATH)/content/popup_item_type_java.target.darwin-arm.mk
diff --git a/GypAndroid.darwin-arm64.mk b/GypAndroid.darwin-arm64.mk
index a193910..1e9a5ba 100644
--- a/GypAndroid.darwin-arm64.mk
+++ b/GypAndroid.darwin-arm64.mk
@@ -81,6 +81,7 @@
 include $(LOCAL_PATH)/content/content_strings_grd.target.darwin-arm64.mk
 include $(LOCAL_PATH)/content/content_utility.target.darwin-arm64.mk
 include $(LOCAL_PATH)/content/gesture_event_type_java.target.darwin-arm64.mk
+include $(LOCAL_PATH)/content/invalidate_types_java.target.darwin-arm64.mk
 include $(LOCAL_PATH)/content/java_set_jni_headers.target.darwin-arm64.mk
 include $(LOCAL_PATH)/content/motionevent_jni_headers.target.darwin-arm64.mk
 include $(LOCAL_PATH)/content/popup_item_type_java.target.darwin-arm64.mk
diff --git a/GypAndroid.darwin-mips.mk b/GypAndroid.darwin-mips.mk
index eea38c9..c3b3b79 100644
--- a/GypAndroid.darwin-mips.mk
+++ b/GypAndroid.darwin-mips.mk
@@ -81,6 +81,7 @@
 include $(LOCAL_PATH)/content/content_strings_grd.target.darwin-mips.mk
 include $(LOCAL_PATH)/content/content_utility.target.darwin-mips.mk
 include $(LOCAL_PATH)/content/gesture_event_type_java.target.darwin-mips.mk
+include $(LOCAL_PATH)/content/invalidate_types_java.target.darwin-mips.mk
 include $(LOCAL_PATH)/content/java_set_jni_headers.target.darwin-mips.mk
 include $(LOCAL_PATH)/content/motionevent_jni_headers.target.darwin-mips.mk
 include $(LOCAL_PATH)/content/popup_item_type_java.target.darwin-mips.mk
diff --git a/GypAndroid.darwin-mips64.mk b/GypAndroid.darwin-mips64.mk
index 3f3fe67..f61f3dd 100644
--- a/GypAndroid.darwin-mips64.mk
+++ b/GypAndroid.darwin-mips64.mk
@@ -81,6 +81,7 @@
 include $(LOCAL_PATH)/content/content_strings_grd.target.darwin-mips64.mk
 include $(LOCAL_PATH)/content/content_utility.target.darwin-mips64.mk
 include $(LOCAL_PATH)/content/gesture_event_type_java.target.darwin-mips64.mk
+include $(LOCAL_PATH)/content/invalidate_types_java.target.darwin-mips64.mk
 include $(LOCAL_PATH)/content/java_set_jni_headers.target.darwin-mips64.mk
 include $(LOCAL_PATH)/content/motionevent_jni_headers.target.darwin-mips64.mk
 include $(LOCAL_PATH)/content/popup_item_type_java.target.darwin-mips64.mk
diff --git a/GypAndroid.darwin-x86.mk b/GypAndroid.darwin-x86.mk
index b5cafff..67b5997 100644
--- a/GypAndroid.darwin-x86.mk
+++ b/GypAndroid.darwin-x86.mk
@@ -81,6 +81,7 @@
 include $(LOCAL_PATH)/content/content_strings_grd.target.darwin-x86.mk
 include $(LOCAL_PATH)/content/content_utility.target.darwin-x86.mk
 include $(LOCAL_PATH)/content/gesture_event_type_java.target.darwin-x86.mk
+include $(LOCAL_PATH)/content/invalidate_types_java.target.darwin-x86.mk
 include $(LOCAL_PATH)/content/java_set_jni_headers.target.darwin-x86.mk
 include $(LOCAL_PATH)/content/motionevent_jni_headers.target.darwin-x86.mk
 include $(LOCAL_PATH)/content/popup_item_type_java.target.darwin-x86.mk
diff --git a/GypAndroid.darwin-x86_64.mk b/GypAndroid.darwin-x86_64.mk
index 96768d7..1e35c79 100644
--- a/GypAndroid.darwin-x86_64.mk
+++ b/GypAndroid.darwin-x86_64.mk
@@ -81,6 +81,7 @@
 include $(LOCAL_PATH)/content/content_strings_grd.target.darwin-x86_64.mk
 include $(LOCAL_PATH)/content/content_utility.target.darwin-x86_64.mk
 include $(LOCAL_PATH)/content/gesture_event_type_java.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/invalidate_types_java.target.darwin-x86_64.mk
 include $(LOCAL_PATH)/content/java_set_jni_headers.target.darwin-x86_64.mk
 include $(LOCAL_PATH)/content/motionevent_jni_headers.target.darwin-x86_64.mk
 include $(LOCAL_PATH)/content/popup_item_type_java.target.darwin-x86_64.mk
diff --git a/GypAndroid.linux-arm.mk b/GypAndroid.linux-arm.mk
index 6c17dcd..7a97ed2 100644
--- a/GypAndroid.linux-arm.mk
+++ b/GypAndroid.linux-arm.mk
@@ -81,6 +81,7 @@
 include $(LOCAL_PATH)/content/content_strings_grd.target.linux-arm.mk
 include $(LOCAL_PATH)/content/content_utility.target.linux-arm.mk
 include $(LOCAL_PATH)/content/gesture_event_type_java.target.linux-arm.mk
+include $(LOCAL_PATH)/content/invalidate_types_java.target.linux-arm.mk
 include $(LOCAL_PATH)/content/java_set_jni_headers.target.linux-arm.mk
 include $(LOCAL_PATH)/content/motionevent_jni_headers.target.linux-arm.mk
 include $(LOCAL_PATH)/content/popup_item_type_java.target.linux-arm.mk
diff --git a/GypAndroid.linux-arm64.mk b/GypAndroid.linux-arm64.mk
index 13a04b6..251900e 100644
--- a/GypAndroid.linux-arm64.mk
+++ b/GypAndroid.linux-arm64.mk
@@ -81,6 +81,7 @@
 include $(LOCAL_PATH)/content/content_strings_grd.target.linux-arm64.mk
 include $(LOCAL_PATH)/content/content_utility.target.linux-arm64.mk
 include $(LOCAL_PATH)/content/gesture_event_type_java.target.linux-arm64.mk
+include $(LOCAL_PATH)/content/invalidate_types_java.target.linux-arm64.mk
 include $(LOCAL_PATH)/content/java_set_jni_headers.target.linux-arm64.mk
 include $(LOCAL_PATH)/content/motionevent_jni_headers.target.linux-arm64.mk
 include $(LOCAL_PATH)/content/popup_item_type_java.target.linux-arm64.mk
diff --git a/GypAndroid.linux-mips.mk b/GypAndroid.linux-mips.mk
index 85654c9..d0d8a86 100644
--- a/GypAndroid.linux-mips.mk
+++ b/GypAndroid.linux-mips.mk
@@ -81,6 +81,7 @@
 include $(LOCAL_PATH)/content/content_strings_grd.target.linux-mips.mk
 include $(LOCAL_PATH)/content/content_utility.target.linux-mips.mk
 include $(LOCAL_PATH)/content/gesture_event_type_java.target.linux-mips.mk
+include $(LOCAL_PATH)/content/invalidate_types_java.target.linux-mips.mk
 include $(LOCAL_PATH)/content/java_set_jni_headers.target.linux-mips.mk
 include $(LOCAL_PATH)/content/motionevent_jni_headers.target.linux-mips.mk
 include $(LOCAL_PATH)/content/popup_item_type_java.target.linux-mips.mk
diff --git a/GypAndroid.linux-mips64.mk b/GypAndroid.linux-mips64.mk
index 88d9d6a..255870c 100644
--- a/GypAndroid.linux-mips64.mk
+++ b/GypAndroid.linux-mips64.mk
@@ -81,6 +81,7 @@
 include $(LOCAL_PATH)/content/content_strings_grd.target.linux-mips64.mk
 include $(LOCAL_PATH)/content/content_utility.target.linux-mips64.mk
 include $(LOCAL_PATH)/content/gesture_event_type_java.target.linux-mips64.mk
+include $(LOCAL_PATH)/content/invalidate_types_java.target.linux-mips64.mk
 include $(LOCAL_PATH)/content/java_set_jni_headers.target.linux-mips64.mk
 include $(LOCAL_PATH)/content/motionevent_jni_headers.target.linux-mips64.mk
 include $(LOCAL_PATH)/content/popup_item_type_java.target.linux-mips64.mk
diff --git a/GypAndroid.linux-x86.mk b/GypAndroid.linux-x86.mk
index 84ece80..8692233 100644
--- a/GypAndroid.linux-x86.mk
+++ b/GypAndroid.linux-x86.mk
@@ -81,6 +81,7 @@
 include $(LOCAL_PATH)/content/content_strings_grd.target.linux-x86.mk
 include $(LOCAL_PATH)/content/content_utility.target.linux-x86.mk
 include $(LOCAL_PATH)/content/gesture_event_type_java.target.linux-x86.mk
+include $(LOCAL_PATH)/content/invalidate_types_java.target.linux-x86.mk
 include $(LOCAL_PATH)/content/java_set_jni_headers.target.linux-x86.mk
 include $(LOCAL_PATH)/content/motionevent_jni_headers.target.linux-x86.mk
 include $(LOCAL_PATH)/content/popup_item_type_java.target.linux-x86.mk
diff --git a/GypAndroid.linux-x86_64.mk b/GypAndroid.linux-x86_64.mk
index 2f1cdc5..0dbe8ce 100644
--- a/GypAndroid.linux-x86_64.mk
+++ b/GypAndroid.linux-x86_64.mk
@@ -81,6 +81,7 @@
 include $(LOCAL_PATH)/content/content_strings_grd.target.linux-x86_64.mk
 include $(LOCAL_PATH)/content/content_utility.target.linux-x86_64.mk
 include $(LOCAL_PATH)/content/gesture_event_type_java.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/invalidate_types_java.target.linux-x86_64.mk
 include $(LOCAL_PATH)/content/java_set_jni_headers.target.linux-x86_64.mk
 include $(LOCAL_PATH)/content/motionevent_jni_headers.target.linux-x86_64.mk
 include $(LOCAL_PATH)/content/popup_item_type_java.target.linux-x86_64.mk
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index b3528e4..b7b30b1 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -50,7 +50,6 @@
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.ContentViewStatics;
 import org.chromium.content.browser.SmartClipProvider;
-import org.chromium.content.browser.WebContentsObserver;
 import org.chromium.content.common.CleanupReference;
 import org.chromium.content_public.browser.GestureStateListener;
 import org.chromium.content_public.browser.JavaScriptCallback;
@@ -190,7 +189,7 @@
     private NavigationController mNavigationController;
     private final AwContentsClient mContentsClient;
     private final AwContentViewClient mContentViewClient;
-    private WebContentsObserver mWebContentsObserver;
+    private AwWebContentsObserver mWebContentsObserver;
     private final AwContentsClientBridge mContentsClientBridge;
     private final AwWebContentsDelegateAdapter mWebContentsDelegate;
     private final AwContentsIoThreadClient mIoThreadClient;
@@ -213,6 +212,8 @@
     private boolean mHasRequestedVisitedHistoryFromClient;
     // TODO(boliu): This should be in a global context, not per webview.
     private final double mDIPScale;
+    // Whether the WebView has attempted to do any load (including uncommitted loads).
+    private boolean mDidAttemptLoad = false;
 
     // The base background color, i.e. not accounting for any CSS body from the current page.
     private int mBaseBackgroundColor = Color.WHITE;
@@ -895,6 +896,9 @@
         if (wasWindowFocused) onWindowFocusChanged(wasWindowFocused);
         if (wasFocused) onFocusChanged(true, 0, null);
 
+        // Popups are always assumed as having made a load attempt.
+        mDidAttemptLoad = true;
+
         // Restore injected JavaScript interfaces.
         for (Map.Entry<String, Pair<Object, Class>> entry : javascriptInterfaces.entrySet()) {
             @SuppressWarnings("unchecked")
@@ -1217,6 +1221,19 @@
         return url;
     }
 
+    /**
+     * Gets the last committed URL. It represents the current page that is
+     * displayed in WebContents. It represents the current security context.
+     *
+     * @return The URL of the current page or null if it's empty.
+     */
+    public String getLastCommittedUrl() {
+        if (isDestroyed()) return null;
+        String url = mWebContents.getLastCommittedUrl();
+        if (url == null || url.trim().isEmpty()) return null;
+        return url;
+    }
+
     public void requestFocus() {
         mAwViewMethods.requestFocus();
     }
@@ -1773,6 +1790,11 @@
         if (!isDestroyed()) mWebContents.evaluateJavaScript(script, null);
     }
 
+    public boolean hasAccessedInitialDocument() {
+        if (isDestroyed()) return false;
+        return mWebContents.hasAccessedInitialDocument();
+    }
+
     //--------------------------------------------------------------------------------------------
     //  View and ViewGroup method implementations
     //--------------------------------------------------------------------------------------------
@@ -1988,6 +2010,12 @@
         if (!isDestroyed()) nativeSetJsOnlineProperty(mNativeAwContents, networkUp);
     }
 
+    public boolean getDidAttemptLoad() {
+        if (mDidAttemptLoad) return mDidAttemptLoad;
+        mDidAttemptLoad = mWebContentsObserver.hasStartedAnyProvisionalLoad();
+        return mDidAttemptLoad;
+    }
+
     //--------------------------------------------------------------------------------------------
     //  Methods called from native via JNI
     //--------------------------------------------------------------------------------------------
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java
index 9adc3bb..053038f 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java
@@ -41,4 +41,8 @@
     // Call in response to a prior runFileChooser call.
     protected static native void nativeFilesSelectedInChooser(int processId, int renderId,
             int modeFlags, String[] filePath, String[] displayName);
+
+    @Override
+    @CalledByNative
+    public abstract void navigationStateChanged(int flags);
 }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
index be714d6..8809ced 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
@@ -11,6 +11,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.provider.MediaStore;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.View;
@@ -20,6 +21,7 @@
 import org.chromium.base.ContentUriUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.content.browser.ContentVideoView;
+import org.chromium.content_public.browser.InvalidateTypes;
 
 /**
  * Adapts the AwWebContentsDelegate interface to the AwContentsClient interface.
@@ -214,6 +216,22 @@
     }
 
     @Override
+    public void navigationStateChanged(int flags) {
+        if ((flags & InvalidateTypes.URL) != 0
+                && mAwContents.hasAccessedInitialDocument()
+                && mAwContents.getDidAttemptLoad()) {
+            // Hint the client to show the last committed url, as it may be unsafe to show
+            // the pending entry.
+            String url = mAwContents.getLastCommittedUrl();
+            url = TextUtils.isEmpty(url) ? "about:blank" : url;
+            mContentsClient.onPageStarted(url);
+            mContentsClient.onLoadResource(url);
+            mContentsClient.onProgressChanged(100);
+            mContentsClient.onPageFinished(url);
+        }
+    }
+
+    @Override
     public void toggleFullscreenModeForTab(boolean enterFullscreen) {
         if (enterFullscreen) {
             mContentViewClient.enterFullscreen();
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java
index c3c381a..cd45ead 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java
@@ -13,12 +13,17 @@
  */
 public class AwWebContentsObserver extends WebContentsObserver {
     private final AwContentsClient mAwContentsClient;
+    private boolean mHasStartedAnyProvisionalLoad = false;
 
     public AwWebContentsObserver(WebContents webContents, AwContentsClient awContentsClient) {
         super(webContents);
         mAwContentsClient = awContentsClient;
     }
 
+    boolean hasStartedAnyProvisionalLoad() {
+        return mHasStartedAnyProvisionalLoad;
+    }
+
     @Override
     public void didFinishLoad(long frameId, String validatedUrl, boolean isMainFrame) {
         String unreachableWebDataUrl = AwContentsStatics.getUnreachableWebDataUrl();
@@ -67,4 +72,15 @@
     public void didNavigateAnyFrame(String url, String baseUrl, boolean isReload) {
         mAwContentsClient.doUpdateVisitedHistory(url, isReload);
     }
+
+    @Override
+    public void didStartProvisionalLoadForFrame(
+            long frameId,
+            long parentFrameId,
+            boolean isMainFrame,
+            String validatedUrl,
+            boolean isErrorPage,
+            boolean isIframeSrcdoc) {
+        mHasStartedAnyProvisionalLoad = true;
+    }
 }
diff --git a/android_webview/java_library_common.mk b/android_webview/java_library_common.mk
index 7697834..b5792ed 100644
--- a/android_webview/java_library_common.mk
+++ b/android_webview/java_library_common.mk
@@ -50,6 +50,7 @@
 $(call intermediates-dir-for,GYP,shared)/enums/content_gamepad_mapping/org/chromium/content/browser/input/CanonicalAxisIndex.java \
 $(call intermediates-dir-for,GYP,shared)/enums/content_gamepad_mapping/org/chromium/content/browser/input/CanonicalButtonIndex.java \
 $(call intermediates-dir-for,GYP,shared)/enums/gesture_event_type_java/org/chromium/content/browser/GestureEventType.java \
+$(call intermediates-dir-for,GYP,shared)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java \
 $(call intermediates-dir-for,GYP,shared)/enums/popup_item_type_java/org/chromium/content/browser/input/PopupItemType.java \
 $(call intermediates-dir-for,GYP,shared)/enums/private_key_types_java/org/chromium/net/PrivateKeyType.java \
 $(call intermediates-dir-for,GYP,shared)/enums/result_codes_java/org/chromium/content_public/common/ResultCode.java \
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java
index 0f62bbd..b657d9d 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/ClientOnPageFinishedTest.java
@@ -276,4 +276,84 @@
             webServer.shutdown();
         }
     }
+
+    @MediumTest
+    @Feature({"AndroidWebView"})
+    public void testOnPageFinishedNotCalledOnDomModificationForBlankWebView() throws Throwable {
+        TestWebServer webServer = TestWebServer.start();
+        try {
+            doTestOnPageFinishedNotCalledOnDomMutation(webServer);
+        } finally {
+            webServer.shutdown();
+        }
+    }
+
+    @MediumTest
+    @Feature({"AndroidWebView"})
+    public void testOnPageFinishedCalledOnDomModificationAfterNonCommittedLoad() throws Throwable {
+        enableJavaScriptOnUiThread(mAwContents);
+        TestWebServer webServer = TestWebServer.start();
+        try {
+            final String noContentUrl = webServer.setResponseWithNoContentStatus("/nocontent.html");
+            TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
+                    mContentsClient.getOnPageFinishedHelper();
+            final int onPageFinishedCallCount = onPageFinishedHelper.getCallCount();
+            loadUrlAsync(mAwContents, noContentUrl);
+            // Mutate DOM.
+            executeJavaScriptAndWaitForResult(mAwContents, mContentsClient,
+                    "document.body.innerHTML='Hello, World!'");
+            onPageFinishedHelper.waitForCallback(onPageFinishedCallCount);
+            assertEquals("about:blank", onPageFinishedHelper.getUrl());
+        } finally {
+            webServer.shutdown();
+        }
+    }
+
+    @MediumTest
+    @Feature({"AndroidWebView"})
+    public void testOnPageFinishedNotCalledOnDomModificationAfterLoadUrl() throws Throwable {
+        TestWebServer webServer = TestWebServer.start();
+        try {
+            final String testUrl =
+                    webServer.setResponse("/test.html", CommonResources.ABOUT_HTML, null);
+            loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), testUrl);
+            doTestOnPageFinishedNotCalledOnDomMutation(webServer);
+        } finally {
+            webServer.shutdown();
+        }
+    }
+
+    @MediumTest
+    @Feature({"AndroidWebView"})
+    public void testOnPageFinishedNotCalledOnDomModificationAfterLoadData()
+            throws Throwable {
+        TestWebServer webServer = TestWebServer.start();
+        try {
+            loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
+                    CommonResources.ABOUT_HTML, "text/html", false);
+            doTestOnPageFinishedNotCalledOnDomMutation(webServer);
+        } finally {
+            webServer.shutdown();
+        }
+    }
+
+    private void doTestOnPageFinishedNotCalledOnDomMutation(TestWebServer webServer)
+            throws Throwable {
+        enableJavaScriptOnUiThread(mAwContents);
+        TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
+                mContentsClient.getOnPageFinishedHelper();
+        final int onPageFinishedCallCount = onPageFinishedHelper.getCallCount();
+        // Mutate DOM.
+        executeJavaScriptAndWaitForResult(mAwContents, mContentsClient,
+                "document.body.innerHTML='Hello, World!'");
+        // Rather than wait a fixed time to see that an onPageFinished callback isn't issued
+        // we load another valid page. Since callbacks arrive sequentially if the next callback
+        // we get is for the synchronizationUrl we know that DOM mutation did not schedule
+        // a callback for the iframe.
+        final String syncUrl = webServer.setResponse("/sync.html", "", null);
+        loadUrlAsync(mAwContents, syncUrl);
+        onPageFinishedHelper.waitForCallback(onPageFinishedCallCount);
+        assertEquals(syncUrl, onPageFinishedHelper.getUrl());
+        assertEquals(onPageFinishedCallCount + 1, onPageFinishedHelper.getCallCount());
+    }
 }
diff --git a/android_webview/libwebviewchromium.gypi b/android_webview/libwebviewchromium.gypi
index c99a6f4..544e051 100644
--- a/android_webview/libwebviewchromium.gypi
+++ b/android_webview/libwebviewchromium.gypi
@@ -18,6 +18,7 @@
         '../base/base.gyp:base_java_memory_pressure_level',
         '../content/content.gyp:content_gamepad_mapping',
         '../content/content.gyp:gesture_event_type_java',
+        '../content/content.gyp:invalidate_types_java',
         '../content/content.gyp:popup_item_type_java',
         '../content/content.gyp:result_codes_java',
         '../content/content.gyp:screen_orientation_values_java',
diff --git a/android_webview/libwebviewchromium.target.darwin-arm.mk b/android_webview/libwebviewchromium.target.darwin-arm.mk
index bce74a8..daf9152 100644
--- a/android_webview/libwebviewchromium.target.darwin-arm.mk
+++ b/android_webview/libwebviewchromium.target.darwin-arm.mk
@@ -18,6 +18,7 @@
 	$(call intermediates-dir-for,GYP,base_base_java_memory_pressure_level_gyp,,,$(GYP_VAR_PREFIX))/base_java_memory_pressure_level.stamp \
 	$(call intermediates-dir-for,GYP,content_content_gamepad_mapping_gyp,,,$(GYP_VAR_PREFIX))/content_gamepad_mapping.stamp \
 	$(call intermediates-dir-for,GYP,content_gesture_event_type_java_gyp,,,$(GYP_VAR_PREFIX))/gesture_event_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_invalidate_types_java_gyp,,,$(GYP_VAR_PREFIX))/invalidate_types_java.stamp \
 	$(call intermediates-dir-for,GYP,content_popup_item_type_java_gyp,,,$(GYP_VAR_PREFIX))/popup_item_type_java.stamp \
 	$(call intermediates-dir-for,GYP,content_result_codes_java_gyp,,,$(GYP_VAR_PREFIX))/result_codes_java.stamp \
 	$(call intermediates-dir-for,GYP,content_screen_orientation_values_java_gyp,,,$(GYP_VAR_PREFIX))/screen_orientation_values_java.stamp \
diff --git a/android_webview/libwebviewchromium.target.darwin-arm64.mk b/android_webview/libwebviewchromium.target.darwin-arm64.mk
index dceafab..cc86866 100644
--- a/android_webview/libwebviewchromium.target.darwin-arm64.mk
+++ b/android_webview/libwebviewchromium.target.darwin-arm64.mk
@@ -18,6 +18,7 @@
 	$(call intermediates-dir-for,GYP,base_base_java_memory_pressure_level_gyp,,,$(GYP_VAR_PREFIX))/base_java_memory_pressure_level.stamp \
 	$(call intermediates-dir-for,GYP,content_content_gamepad_mapping_gyp,,,$(GYP_VAR_PREFIX))/content_gamepad_mapping.stamp \
 	$(call intermediates-dir-for,GYP,content_gesture_event_type_java_gyp,,,$(GYP_VAR_PREFIX))/gesture_event_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_invalidate_types_java_gyp,,,$(GYP_VAR_PREFIX))/invalidate_types_java.stamp \
 	$(call intermediates-dir-for,GYP,content_popup_item_type_java_gyp,,,$(GYP_VAR_PREFIX))/popup_item_type_java.stamp \
 	$(call intermediates-dir-for,GYP,content_result_codes_java_gyp,,,$(GYP_VAR_PREFIX))/result_codes_java.stamp \
 	$(call intermediates-dir-for,GYP,content_screen_orientation_values_java_gyp,,,$(GYP_VAR_PREFIX))/screen_orientation_values_java.stamp \
diff --git a/android_webview/libwebviewchromium.target.darwin-mips.mk b/android_webview/libwebviewchromium.target.darwin-mips.mk
index 6c489f1..833116c 100644
--- a/android_webview/libwebviewchromium.target.darwin-mips.mk
+++ b/android_webview/libwebviewchromium.target.darwin-mips.mk
@@ -18,6 +18,7 @@
 	$(call intermediates-dir-for,GYP,base_base_java_memory_pressure_level_gyp,,,$(GYP_VAR_PREFIX))/base_java_memory_pressure_level.stamp \
 	$(call intermediates-dir-for,GYP,content_content_gamepad_mapping_gyp,,,$(GYP_VAR_PREFIX))/content_gamepad_mapping.stamp \
 	$(call intermediates-dir-for,GYP,content_gesture_event_type_java_gyp,,,$(GYP_VAR_PREFIX))/gesture_event_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_invalidate_types_java_gyp,,,$(GYP_VAR_PREFIX))/invalidate_types_java.stamp \
 	$(call intermediates-dir-for,GYP,content_popup_item_type_java_gyp,,,$(GYP_VAR_PREFIX))/popup_item_type_java.stamp \
 	$(call intermediates-dir-for,GYP,content_result_codes_java_gyp,,,$(GYP_VAR_PREFIX))/result_codes_java.stamp \
 	$(call intermediates-dir-for,GYP,content_screen_orientation_values_java_gyp,,,$(GYP_VAR_PREFIX))/screen_orientation_values_java.stamp \
diff --git a/android_webview/libwebviewchromium.target.darwin-mips64.mk b/android_webview/libwebviewchromium.target.darwin-mips64.mk
index b1ba66a..2ae79c2 100644
--- a/android_webview/libwebviewchromium.target.darwin-mips64.mk
+++ b/android_webview/libwebviewchromium.target.darwin-mips64.mk
@@ -18,6 +18,7 @@
 	$(call intermediates-dir-for,GYP,base_base_java_memory_pressure_level_gyp,,,$(GYP_VAR_PREFIX))/base_java_memory_pressure_level.stamp \
 	$(call intermediates-dir-for,GYP,content_content_gamepad_mapping_gyp,,,$(GYP_VAR_PREFIX))/content_gamepad_mapping.stamp \
 	$(call intermediates-dir-for,GYP,content_gesture_event_type_java_gyp,,,$(GYP_VAR_PREFIX))/gesture_event_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_invalidate_types_java_gyp,,,$(GYP_VAR_PREFIX))/invalidate_types_java.stamp \
 	$(call intermediates-dir-for,GYP,content_popup_item_type_java_gyp,,,$(GYP_VAR_PREFIX))/popup_item_type_java.stamp \
 	$(call intermediates-dir-for,GYP,content_result_codes_java_gyp,,,$(GYP_VAR_PREFIX))/result_codes_java.stamp \
 	$(call intermediates-dir-for,GYP,content_screen_orientation_values_java_gyp,,,$(GYP_VAR_PREFIX))/screen_orientation_values_java.stamp \
diff --git a/android_webview/libwebviewchromium.target.darwin-x86.mk b/android_webview/libwebviewchromium.target.darwin-x86.mk
index d4510db..00d4d37 100644
--- a/android_webview/libwebviewchromium.target.darwin-x86.mk
+++ b/android_webview/libwebviewchromium.target.darwin-x86.mk
@@ -18,6 +18,7 @@
 	$(call intermediates-dir-for,GYP,base_base_java_memory_pressure_level_gyp,,,$(GYP_VAR_PREFIX))/base_java_memory_pressure_level.stamp \
 	$(call intermediates-dir-for,GYP,content_content_gamepad_mapping_gyp,,,$(GYP_VAR_PREFIX))/content_gamepad_mapping.stamp \
 	$(call intermediates-dir-for,GYP,content_gesture_event_type_java_gyp,,,$(GYP_VAR_PREFIX))/gesture_event_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_invalidate_types_java_gyp,,,$(GYP_VAR_PREFIX))/invalidate_types_java.stamp \
 	$(call intermediates-dir-for,GYP,content_popup_item_type_java_gyp,,,$(GYP_VAR_PREFIX))/popup_item_type_java.stamp \
 	$(call intermediates-dir-for,GYP,content_result_codes_java_gyp,,,$(GYP_VAR_PREFIX))/result_codes_java.stamp \
 	$(call intermediates-dir-for,GYP,content_screen_orientation_values_java_gyp,,,$(GYP_VAR_PREFIX))/screen_orientation_values_java.stamp \
diff --git a/android_webview/libwebviewchromium.target.darwin-x86_64.mk b/android_webview/libwebviewchromium.target.darwin-x86_64.mk
index 32f7d4c..f4f21cc 100644
--- a/android_webview/libwebviewchromium.target.darwin-x86_64.mk
+++ b/android_webview/libwebviewchromium.target.darwin-x86_64.mk
@@ -18,6 +18,7 @@
 	$(call intermediates-dir-for,GYP,base_base_java_memory_pressure_level_gyp,,,$(GYP_VAR_PREFIX))/base_java_memory_pressure_level.stamp \
 	$(call intermediates-dir-for,GYP,content_content_gamepad_mapping_gyp,,,$(GYP_VAR_PREFIX))/content_gamepad_mapping.stamp \
 	$(call intermediates-dir-for,GYP,content_gesture_event_type_java_gyp,,,$(GYP_VAR_PREFIX))/gesture_event_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_invalidate_types_java_gyp,,,$(GYP_VAR_PREFIX))/invalidate_types_java.stamp \
 	$(call intermediates-dir-for,GYP,content_popup_item_type_java_gyp,,,$(GYP_VAR_PREFIX))/popup_item_type_java.stamp \
 	$(call intermediates-dir-for,GYP,content_result_codes_java_gyp,,,$(GYP_VAR_PREFIX))/result_codes_java.stamp \
 	$(call intermediates-dir-for,GYP,content_screen_orientation_values_java_gyp,,,$(GYP_VAR_PREFIX))/screen_orientation_values_java.stamp \
diff --git a/android_webview/libwebviewchromium.target.linux-arm.mk b/android_webview/libwebviewchromium.target.linux-arm.mk
index bce74a8..daf9152 100644
--- a/android_webview/libwebviewchromium.target.linux-arm.mk
+++ b/android_webview/libwebviewchromium.target.linux-arm.mk
@@ -18,6 +18,7 @@
 	$(call intermediates-dir-for,GYP,base_base_java_memory_pressure_level_gyp,,,$(GYP_VAR_PREFIX))/base_java_memory_pressure_level.stamp \
 	$(call intermediates-dir-for,GYP,content_content_gamepad_mapping_gyp,,,$(GYP_VAR_PREFIX))/content_gamepad_mapping.stamp \
 	$(call intermediates-dir-for,GYP,content_gesture_event_type_java_gyp,,,$(GYP_VAR_PREFIX))/gesture_event_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_invalidate_types_java_gyp,,,$(GYP_VAR_PREFIX))/invalidate_types_java.stamp \
 	$(call intermediates-dir-for,GYP,content_popup_item_type_java_gyp,,,$(GYP_VAR_PREFIX))/popup_item_type_java.stamp \
 	$(call intermediates-dir-for,GYP,content_result_codes_java_gyp,,,$(GYP_VAR_PREFIX))/result_codes_java.stamp \
 	$(call intermediates-dir-for,GYP,content_screen_orientation_values_java_gyp,,,$(GYP_VAR_PREFIX))/screen_orientation_values_java.stamp \
diff --git a/android_webview/libwebviewchromium.target.linux-arm64.mk b/android_webview/libwebviewchromium.target.linux-arm64.mk
index dceafab..cc86866 100644
--- a/android_webview/libwebviewchromium.target.linux-arm64.mk
+++ b/android_webview/libwebviewchromium.target.linux-arm64.mk
@@ -18,6 +18,7 @@
 	$(call intermediates-dir-for,GYP,base_base_java_memory_pressure_level_gyp,,,$(GYP_VAR_PREFIX))/base_java_memory_pressure_level.stamp \
 	$(call intermediates-dir-for,GYP,content_content_gamepad_mapping_gyp,,,$(GYP_VAR_PREFIX))/content_gamepad_mapping.stamp \
 	$(call intermediates-dir-for,GYP,content_gesture_event_type_java_gyp,,,$(GYP_VAR_PREFIX))/gesture_event_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_invalidate_types_java_gyp,,,$(GYP_VAR_PREFIX))/invalidate_types_java.stamp \
 	$(call intermediates-dir-for,GYP,content_popup_item_type_java_gyp,,,$(GYP_VAR_PREFIX))/popup_item_type_java.stamp \
 	$(call intermediates-dir-for,GYP,content_result_codes_java_gyp,,,$(GYP_VAR_PREFIX))/result_codes_java.stamp \
 	$(call intermediates-dir-for,GYP,content_screen_orientation_values_java_gyp,,,$(GYP_VAR_PREFIX))/screen_orientation_values_java.stamp \
diff --git a/android_webview/libwebviewchromium.target.linux-mips.mk b/android_webview/libwebviewchromium.target.linux-mips.mk
index 6c489f1..833116c 100644
--- a/android_webview/libwebviewchromium.target.linux-mips.mk
+++ b/android_webview/libwebviewchromium.target.linux-mips.mk
@@ -18,6 +18,7 @@
 	$(call intermediates-dir-for,GYP,base_base_java_memory_pressure_level_gyp,,,$(GYP_VAR_PREFIX))/base_java_memory_pressure_level.stamp \
 	$(call intermediates-dir-for,GYP,content_content_gamepad_mapping_gyp,,,$(GYP_VAR_PREFIX))/content_gamepad_mapping.stamp \
 	$(call intermediates-dir-for,GYP,content_gesture_event_type_java_gyp,,,$(GYP_VAR_PREFIX))/gesture_event_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_invalidate_types_java_gyp,,,$(GYP_VAR_PREFIX))/invalidate_types_java.stamp \
 	$(call intermediates-dir-for,GYP,content_popup_item_type_java_gyp,,,$(GYP_VAR_PREFIX))/popup_item_type_java.stamp \
 	$(call intermediates-dir-for,GYP,content_result_codes_java_gyp,,,$(GYP_VAR_PREFIX))/result_codes_java.stamp \
 	$(call intermediates-dir-for,GYP,content_screen_orientation_values_java_gyp,,,$(GYP_VAR_PREFIX))/screen_orientation_values_java.stamp \
diff --git a/android_webview/libwebviewchromium.target.linux-mips64.mk b/android_webview/libwebviewchromium.target.linux-mips64.mk
index b1ba66a..2ae79c2 100644
--- a/android_webview/libwebviewchromium.target.linux-mips64.mk
+++ b/android_webview/libwebviewchromium.target.linux-mips64.mk
@@ -18,6 +18,7 @@
 	$(call intermediates-dir-for,GYP,base_base_java_memory_pressure_level_gyp,,,$(GYP_VAR_PREFIX))/base_java_memory_pressure_level.stamp \
 	$(call intermediates-dir-for,GYP,content_content_gamepad_mapping_gyp,,,$(GYP_VAR_PREFIX))/content_gamepad_mapping.stamp \
 	$(call intermediates-dir-for,GYP,content_gesture_event_type_java_gyp,,,$(GYP_VAR_PREFIX))/gesture_event_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_invalidate_types_java_gyp,,,$(GYP_VAR_PREFIX))/invalidate_types_java.stamp \
 	$(call intermediates-dir-for,GYP,content_popup_item_type_java_gyp,,,$(GYP_VAR_PREFIX))/popup_item_type_java.stamp \
 	$(call intermediates-dir-for,GYP,content_result_codes_java_gyp,,,$(GYP_VAR_PREFIX))/result_codes_java.stamp \
 	$(call intermediates-dir-for,GYP,content_screen_orientation_values_java_gyp,,,$(GYP_VAR_PREFIX))/screen_orientation_values_java.stamp \
diff --git a/android_webview/libwebviewchromium.target.linux-x86.mk b/android_webview/libwebviewchromium.target.linux-x86.mk
index d4510db..00d4d37 100644
--- a/android_webview/libwebviewchromium.target.linux-x86.mk
+++ b/android_webview/libwebviewchromium.target.linux-x86.mk
@@ -18,6 +18,7 @@
 	$(call intermediates-dir-for,GYP,base_base_java_memory_pressure_level_gyp,,,$(GYP_VAR_PREFIX))/base_java_memory_pressure_level.stamp \
 	$(call intermediates-dir-for,GYP,content_content_gamepad_mapping_gyp,,,$(GYP_VAR_PREFIX))/content_gamepad_mapping.stamp \
 	$(call intermediates-dir-for,GYP,content_gesture_event_type_java_gyp,,,$(GYP_VAR_PREFIX))/gesture_event_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_invalidate_types_java_gyp,,,$(GYP_VAR_PREFIX))/invalidate_types_java.stamp \
 	$(call intermediates-dir-for,GYP,content_popup_item_type_java_gyp,,,$(GYP_VAR_PREFIX))/popup_item_type_java.stamp \
 	$(call intermediates-dir-for,GYP,content_result_codes_java_gyp,,,$(GYP_VAR_PREFIX))/result_codes_java.stamp \
 	$(call intermediates-dir-for,GYP,content_screen_orientation_values_java_gyp,,,$(GYP_VAR_PREFIX))/screen_orientation_values_java.stamp \
diff --git a/android_webview/libwebviewchromium.target.linux-x86_64.mk b/android_webview/libwebviewchromium.target.linux-x86_64.mk
index 32f7d4c..f4f21cc 100644
--- a/android_webview/libwebviewchromium.target.linux-x86_64.mk
+++ b/android_webview/libwebviewchromium.target.linux-x86_64.mk
@@ -18,6 +18,7 @@
 	$(call intermediates-dir-for,GYP,base_base_java_memory_pressure_level_gyp,,,$(GYP_VAR_PREFIX))/base_java_memory_pressure_level.stamp \
 	$(call intermediates-dir-for,GYP,content_content_gamepad_mapping_gyp,,,$(GYP_VAR_PREFIX))/content_gamepad_mapping.stamp \
 	$(call intermediates-dir-for,GYP,content_gesture_event_type_java_gyp,,,$(GYP_VAR_PREFIX))/gesture_event_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_invalidate_types_java_gyp,,,$(GYP_VAR_PREFIX))/invalidate_types_java.stamp \
 	$(call intermediates-dir-for,GYP,content_popup_item_type_java_gyp,,,$(GYP_VAR_PREFIX))/popup_item_type_java.stamp \
 	$(call intermediates-dir-for,GYP,content_result_codes_java_gyp,,,$(GYP_VAR_PREFIX))/result_codes_java.stamp \
 	$(call intermediates-dir-for,GYP,content_screen_orientation_values_java_gyp,,,$(GYP_VAR_PREFIX))/screen_orientation_values_java.stamp \
diff --git a/android_webview/native/aw_web_contents_delegate.cc b/android_webview/native/aw_web_contents_delegate.cc
index ff73c1d..27efec4 100644
--- a/android_webview/native/aw_web_contents_delegate.cc
+++ b/android_webview/native/aw_web_contents_delegate.cc
@@ -163,6 +163,18 @@
   }
 }
 
+void AwWebContentsDelegate::NavigationStateChanged(
+    const content::WebContents* source,
+    content::InvalidateTypes changed_flags) {
+  JNIEnv* env = AttachCurrentThread();
+
+  ScopedJavaLocalRef<jobject> java_delegate = GetJavaDelegate(env);
+  if (java_delegate.obj()) {
+    Java_AwWebContentsDelegate_navigationStateChanged(env, java_delegate.obj(),
+                                                      changed_flags);
+  }
+}
+
 // Notifies the delegate about the creation of a new WebContents. This
 // typically happens when popups are created.
 void AwWebContentsDelegate::WebContentsCreated(
diff --git a/android_webview/native/aw_web_contents_delegate.h b/android_webview/native/aw_web_contents_delegate.h
index f45d312..e898b84 100644
--- a/android_webview/native/aw_web_contents_delegate.h
+++ b/android_webview/native/aw_web_contents_delegate.h
@@ -41,6 +41,9 @@
                               bool user_gesture,
                               bool* was_blocked) override;
 
+  virtual void NavigationStateChanged(
+      const content::WebContents* source,
+      content::InvalidateTypes changed_flags) override;
   virtual void WebContentsCreated(content::WebContents* source_contents,
                                   int opener_render_frame_id,
                                   const base::string16& frame_name,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/Tab.java
index dda3131..59ad605 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/Tab.java
@@ -33,6 +33,7 @@
 import org.chromium.content.browser.ContentViewClient;
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.WebContentsObserver;
+import org.chromium.content_public.browser.InvalidateTypes;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.Clipboard;
@@ -244,10 +245,10 @@
 
         @Override
         public void navigationStateChanged(int flags) {
-            if ((flags & INVALIDATE_TYPE_TITLE) != 0) {
+            if ((flags & InvalidateTypes.TITLE) != 0) {
                 for (TabObserver observer : mObservers) observer.onTitleUpdated(Tab.this);
             }
-            if ((flags & INVALIDATE_TYPE_URL) != 0) {
+            if ((flags & InvalidateTypes.URL) != 0) {
                 for (TabObserver observer : mObservers) observer.onUrlUpdated(Tab.this);
             }
         }
diff --git a/components/web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/WebContentsDelegateAndroid.java b/components/web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/WebContentsDelegateAndroid.java
index 5e56253..df6b12f 100644
--- a/components/web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/WebContentsDelegateAndroid.java
+++ b/components/web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/WebContentsDelegateAndroid.java
@@ -8,6 +8,7 @@
 
 import org.chromium.base.CalledByNative;
 import org.chromium.base.JNINamespace;
+import org.chromium.content_public.browser.InvalidateTypes;
 
 /**
  * Java peer of the native class of the same name.
@@ -24,16 +25,8 @@
     // Equivalent of WebCore::WebConsoleMessage::LevelError.
     public static final int LOG_LEVEL_ERROR = 3;
 
-    // Flags passed to the WebContentsDelegateAndroid.navigationStateChanged to tell it
-    // what has changed. Should match the values in invalidate_type.h.
-    // Equivalent of InvalidateTypes::INVALIDATE_TYPE_URL.
-    public static final int INVALIDATE_TYPE_URL = 1 << 0;
-    // Equivalent of InvalidateTypes::INVALIDATE_TYPE_TAB.
-    public static final int INVALIDATE_TYPE_TAB = 1 << 1;
-    // Equivalent of InvalidateTypes::INVALIDATE_TYPE_LOAD.
-    public static final int INVALIDATE_TYPE_LOAD = 1 << 2;
-    // Equivalent of InvalidateTypes::INVALIDATE_TYPE_TITLE.
-    public static final int INVALIDATE_TYPE_TITLE = 1 << 3;
+    // TODO(mnaganov): Remove after getting rid of downstream usages.
+    public static final int INVALIDATE_TYPE_TAB = InvalidateTypes.TAB;
 
     // The most recent load progress callback received from WebContents, as a percentage.
     // Initialize to 100 to indicate that we're not in a loading state.
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc
index 85490c1..b38f684 100644
--- a/content/browser/web_contents/web_contents_android.cc
+++ b/content/browser/web_contents/web_contents_android.cc
@@ -141,6 +141,14 @@
   return ConvertUTF8ToJavaString(env, web_contents_->GetURL().spec());
 }
 
+ScopedJavaLocalRef<jstring> WebContentsAndroid::GetLastCommittedURL(
+    JNIEnv* env,
+    jobject) const {
+  return ConvertUTF8ToJavaString(env,
+                                 web_contents_->GetLastCommittedURL().spec());
+}
+
+
 jboolean WebContentsAndroid::IsIncognito(JNIEnv* env, jobject obj) {
   return web_contents_->GetBrowserContext()->IsOffTheRecord();
 }
@@ -396,4 +404,11 @@
   host->Send(new ViewMsg_PostMessageEvent(host->GetRoutingID(), params));
 }
 
+jboolean WebContentsAndroid::HasAccessedInitialDocument(
+    JNIEnv* env,
+    jobject jobj) {
+  return static_cast<content::WebContentsImpl*>(web_contents_)->
+      HasAccessedInitialDocument();
+}
+
 }  // namespace content
diff --git a/content/browser/web_contents/web_contents_android.h b/content/browser/web_contents/web_contents_android.h
index 4b79231..68c3cfa 100644
--- a/content/browser/web_contents/web_contents_android.h
+++ b/content/browser/web_contents/web_contents_android.h
@@ -48,6 +48,8 @@
   void Stop(JNIEnv* env, jobject obj);
   jint GetBackgroundColor(JNIEnv* env, jobject obj);
   base::android::ScopedJavaLocalRef<jstring> GetURL(JNIEnv* env, jobject) const;
+  base::android::ScopedJavaLocalRef<jstring> GetLastCommittedURL(JNIEnv* env,
+                                                                 jobject) const;
   jboolean IsIncognito(JNIEnv* env, jobject obj);
 
   void ResumeResponseDeferredAtStart(JNIEnv* env, jobject obj);
@@ -95,6 +97,9 @@
                           jobject callback);
   void PostMessageToFrame(JNIEnv* env, jobject obj, jstring frame_id,
       jstring message, jstring source_origin, jstring target_origin);
+
+  jboolean HasAccessedInitialDocument(JNIEnv* env, jobject jobj);
+
  private:
   RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid();
 
diff --git a/content/content.gyp b/content/content.gyp
index 5a7355f..c2e33e2 100644
--- a/content/content.gyp
+++ b/content/content.gyp
@@ -435,6 +435,7 @@
             'content_strings_grd',
             'content_gamepad_mapping',
             'gesture_event_type_java',
+            'invalidate_types_java',
             'popup_item_type_java',
             'result_codes_java',
             'selection_event_type_java',
@@ -494,6 +495,14 @@
           'includes': [ '../build/android/java_cpp_enum.gypi' ],
         },
         {
+          'target_name': 'invalidate_types_java',
+          'type': 'none',
+          'variables': {
+            'source_file': 'public/browser/invalidate_type.h',
+          },
+          'includes': [ '../build/android/java_cpp_enum.gypi' ],
+        },
+        {
           'target_name': 'result_codes_java',
           'type': 'none',
           'variables': {
diff --git a/content/invalidate_types_java.target.darwin-arm.mk b/content/invalidate_types_java.target.darwin-arm.mk
new file mode 100644
index 0000000..addab3e
--- /dev/null
+++ b/content/invalidate_types_java.target.darwin-arm.mk
@@ -0,0 +1,59 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_invalidate_types_java_gyp
+LOCAL_MODULE_STEM := invalidate_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TARGET_ARCH := $(TARGET_$(GYP_VAR_PREFIX)ARCH)
+LOCAL_SDK_VERSION := 21
+gyp_intermediate_dir := $(call local-intermediates-dir,,$(GYP_VAR_PREFIX))
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_java_constants":
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_var_prefix := $(GYP_VAR_PREFIX)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/java_cpp_enum.py $(LOCAL_PATH)/content/public/browser/invalidate_type.h $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating Java from cpp header public/browser/invalidate_type.h ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser; python ../build/android/gyp/java_cpp_enum.py "--output_dir=$(gyp_shared_intermediate_dir)/enums/invalidate_types_java" public/browser/invalidate_type.h
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+### Set directly by aosp_build_settings.
+LOCAL_CLANG := false
+LOCAL_NDK_STL_VARIANT := stlport_static
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_invalidate_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: invalidate_types_java
+invalidate_types_java: content_invalidate_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
+
+LOCAL_2ND_ARCH_VAR_PREFIX :=
diff --git a/content/invalidate_types_java.target.darwin-arm64.mk b/content/invalidate_types_java.target.darwin-arm64.mk
new file mode 100644
index 0000000..addab3e
--- /dev/null
+++ b/content/invalidate_types_java.target.darwin-arm64.mk
@@ -0,0 +1,59 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_invalidate_types_java_gyp
+LOCAL_MODULE_STEM := invalidate_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TARGET_ARCH := $(TARGET_$(GYP_VAR_PREFIX)ARCH)
+LOCAL_SDK_VERSION := 21
+gyp_intermediate_dir := $(call local-intermediates-dir,,$(GYP_VAR_PREFIX))
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_java_constants":
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_var_prefix := $(GYP_VAR_PREFIX)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/java_cpp_enum.py $(LOCAL_PATH)/content/public/browser/invalidate_type.h $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating Java from cpp header public/browser/invalidate_type.h ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser; python ../build/android/gyp/java_cpp_enum.py "--output_dir=$(gyp_shared_intermediate_dir)/enums/invalidate_types_java" public/browser/invalidate_type.h
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+### Set directly by aosp_build_settings.
+LOCAL_CLANG := false
+LOCAL_NDK_STL_VARIANT := stlport_static
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_invalidate_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: invalidate_types_java
+invalidate_types_java: content_invalidate_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
+
+LOCAL_2ND_ARCH_VAR_PREFIX :=
diff --git a/content/invalidate_types_java.target.darwin-mips.mk b/content/invalidate_types_java.target.darwin-mips.mk
new file mode 100644
index 0000000..addab3e
--- /dev/null
+++ b/content/invalidate_types_java.target.darwin-mips.mk
@@ -0,0 +1,59 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_invalidate_types_java_gyp
+LOCAL_MODULE_STEM := invalidate_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TARGET_ARCH := $(TARGET_$(GYP_VAR_PREFIX)ARCH)
+LOCAL_SDK_VERSION := 21
+gyp_intermediate_dir := $(call local-intermediates-dir,,$(GYP_VAR_PREFIX))
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_java_constants":
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_var_prefix := $(GYP_VAR_PREFIX)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/java_cpp_enum.py $(LOCAL_PATH)/content/public/browser/invalidate_type.h $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating Java from cpp header public/browser/invalidate_type.h ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser; python ../build/android/gyp/java_cpp_enum.py "--output_dir=$(gyp_shared_intermediate_dir)/enums/invalidate_types_java" public/browser/invalidate_type.h
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+### Set directly by aosp_build_settings.
+LOCAL_CLANG := false
+LOCAL_NDK_STL_VARIANT := stlport_static
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_invalidate_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: invalidate_types_java
+invalidate_types_java: content_invalidate_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
+
+LOCAL_2ND_ARCH_VAR_PREFIX :=
diff --git a/content/invalidate_types_java.target.darwin-mips64.mk b/content/invalidate_types_java.target.darwin-mips64.mk
new file mode 100644
index 0000000..addab3e
--- /dev/null
+++ b/content/invalidate_types_java.target.darwin-mips64.mk
@@ -0,0 +1,59 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_invalidate_types_java_gyp
+LOCAL_MODULE_STEM := invalidate_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TARGET_ARCH := $(TARGET_$(GYP_VAR_PREFIX)ARCH)
+LOCAL_SDK_VERSION := 21
+gyp_intermediate_dir := $(call local-intermediates-dir,,$(GYP_VAR_PREFIX))
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_java_constants":
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_var_prefix := $(GYP_VAR_PREFIX)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/java_cpp_enum.py $(LOCAL_PATH)/content/public/browser/invalidate_type.h $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating Java from cpp header public/browser/invalidate_type.h ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser; python ../build/android/gyp/java_cpp_enum.py "--output_dir=$(gyp_shared_intermediate_dir)/enums/invalidate_types_java" public/browser/invalidate_type.h
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+### Set directly by aosp_build_settings.
+LOCAL_CLANG := false
+LOCAL_NDK_STL_VARIANT := stlport_static
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_invalidate_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: invalidate_types_java
+invalidate_types_java: content_invalidate_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
+
+LOCAL_2ND_ARCH_VAR_PREFIX :=
diff --git a/content/invalidate_types_java.target.darwin-x86.mk b/content/invalidate_types_java.target.darwin-x86.mk
new file mode 100644
index 0000000..addab3e
--- /dev/null
+++ b/content/invalidate_types_java.target.darwin-x86.mk
@@ -0,0 +1,59 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_invalidate_types_java_gyp
+LOCAL_MODULE_STEM := invalidate_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TARGET_ARCH := $(TARGET_$(GYP_VAR_PREFIX)ARCH)
+LOCAL_SDK_VERSION := 21
+gyp_intermediate_dir := $(call local-intermediates-dir,,$(GYP_VAR_PREFIX))
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_java_constants":
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_var_prefix := $(GYP_VAR_PREFIX)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/java_cpp_enum.py $(LOCAL_PATH)/content/public/browser/invalidate_type.h $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating Java from cpp header public/browser/invalidate_type.h ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser; python ../build/android/gyp/java_cpp_enum.py "--output_dir=$(gyp_shared_intermediate_dir)/enums/invalidate_types_java" public/browser/invalidate_type.h
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+### Set directly by aosp_build_settings.
+LOCAL_CLANG := false
+LOCAL_NDK_STL_VARIANT := stlport_static
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_invalidate_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: invalidate_types_java
+invalidate_types_java: content_invalidate_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
+
+LOCAL_2ND_ARCH_VAR_PREFIX :=
diff --git a/content/invalidate_types_java.target.darwin-x86_64.mk b/content/invalidate_types_java.target.darwin-x86_64.mk
new file mode 100644
index 0000000..addab3e
--- /dev/null
+++ b/content/invalidate_types_java.target.darwin-x86_64.mk
@@ -0,0 +1,59 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_invalidate_types_java_gyp
+LOCAL_MODULE_STEM := invalidate_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TARGET_ARCH := $(TARGET_$(GYP_VAR_PREFIX)ARCH)
+LOCAL_SDK_VERSION := 21
+gyp_intermediate_dir := $(call local-intermediates-dir,,$(GYP_VAR_PREFIX))
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_java_constants":
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_var_prefix := $(GYP_VAR_PREFIX)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/java_cpp_enum.py $(LOCAL_PATH)/content/public/browser/invalidate_type.h $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating Java from cpp header public/browser/invalidate_type.h ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser; python ../build/android/gyp/java_cpp_enum.py "--output_dir=$(gyp_shared_intermediate_dir)/enums/invalidate_types_java" public/browser/invalidate_type.h
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+### Set directly by aosp_build_settings.
+LOCAL_CLANG := false
+LOCAL_NDK_STL_VARIANT := stlport_static
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_invalidate_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: invalidate_types_java
+invalidate_types_java: content_invalidate_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
+
+LOCAL_2ND_ARCH_VAR_PREFIX :=
diff --git a/content/invalidate_types_java.target.linux-arm.mk b/content/invalidate_types_java.target.linux-arm.mk
new file mode 100644
index 0000000..addab3e
--- /dev/null
+++ b/content/invalidate_types_java.target.linux-arm.mk
@@ -0,0 +1,59 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_invalidate_types_java_gyp
+LOCAL_MODULE_STEM := invalidate_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TARGET_ARCH := $(TARGET_$(GYP_VAR_PREFIX)ARCH)
+LOCAL_SDK_VERSION := 21
+gyp_intermediate_dir := $(call local-intermediates-dir,,$(GYP_VAR_PREFIX))
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_java_constants":
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_var_prefix := $(GYP_VAR_PREFIX)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/java_cpp_enum.py $(LOCAL_PATH)/content/public/browser/invalidate_type.h $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating Java from cpp header public/browser/invalidate_type.h ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser; python ../build/android/gyp/java_cpp_enum.py "--output_dir=$(gyp_shared_intermediate_dir)/enums/invalidate_types_java" public/browser/invalidate_type.h
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+### Set directly by aosp_build_settings.
+LOCAL_CLANG := false
+LOCAL_NDK_STL_VARIANT := stlport_static
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_invalidate_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: invalidate_types_java
+invalidate_types_java: content_invalidate_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
+
+LOCAL_2ND_ARCH_VAR_PREFIX :=
diff --git a/content/invalidate_types_java.target.linux-arm64.mk b/content/invalidate_types_java.target.linux-arm64.mk
new file mode 100644
index 0000000..addab3e
--- /dev/null
+++ b/content/invalidate_types_java.target.linux-arm64.mk
@@ -0,0 +1,59 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_invalidate_types_java_gyp
+LOCAL_MODULE_STEM := invalidate_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TARGET_ARCH := $(TARGET_$(GYP_VAR_PREFIX)ARCH)
+LOCAL_SDK_VERSION := 21
+gyp_intermediate_dir := $(call local-intermediates-dir,,$(GYP_VAR_PREFIX))
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_java_constants":
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_var_prefix := $(GYP_VAR_PREFIX)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/java_cpp_enum.py $(LOCAL_PATH)/content/public/browser/invalidate_type.h $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating Java from cpp header public/browser/invalidate_type.h ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser; python ../build/android/gyp/java_cpp_enum.py "--output_dir=$(gyp_shared_intermediate_dir)/enums/invalidate_types_java" public/browser/invalidate_type.h
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+### Set directly by aosp_build_settings.
+LOCAL_CLANG := false
+LOCAL_NDK_STL_VARIANT := stlport_static
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_invalidate_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: invalidate_types_java
+invalidate_types_java: content_invalidate_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
+
+LOCAL_2ND_ARCH_VAR_PREFIX :=
diff --git a/content/invalidate_types_java.target.linux-mips.mk b/content/invalidate_types_java.target.linux-mips.mk
new file mode 100644
index 0000000..addab3e
--- /dev/null
+++ b/content/invalidate_types_java.target.linux-mips.mk
@@ -0,0 +1,59 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_invalidate_types_java_gyp
+LOCAL_MODULE_STEM := invalidate_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TARGET_ARCH := $(TARGET_$(GYP_VAR_PREFIX)ARCH)
+LOCAL_SDK_VERSION := 21
+gyp_intermediate_dir := $(call local-intermediates-dir,,$(GYP_VAR_PREFIX))
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_java_constants":
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_var_prefix := $(GYP_VAR_PREFIX)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/java_cpp_enum.py $(LOCAL_PATH)/content/public/browser/invalidate_type.h $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating Java from cpp header public/browser/invalidate_type.h ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser; python ../build/android/gyp/java_cpp_enum.py "--output_dir=$(gyp_shared_intermediate_dir)/enums/invalidate_types_java" public/browser/invalidate_type.h
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+### Set directly by aosp_build_settings.
+LOCAL_CLANG := false
+LOCAL_NDK_STL_VARIANT := stlport_static
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_invalidate_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: invalidate_types_java
+invalidate_types_java: content_invalidate_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
+
+LOCAL_2ND_ARCH_VAR_PREFIX :=
diff --git a/content/invalidate_types_java.target.linux-mips64.mk b/content/invalidate_types_java.target.linux-mips64.mk
new file mode 100644
index 0000000..addab3e
--- /dev/null
+++ b/content/invalidate_types_java.target.linux-mips64.mk
@@ -0,0 +1,59 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_invalidate_types_java_gyp
+LOCAL_MODULE_STEM := invalidate_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TARGET_ARCH := $(TARGET_$(GYP_VAR_PREFIX)ARCH)
+LOCAL_SDK_VERSION := 21
+gyp_intermediate_dir := $(call local-intermediates-dir,,$(GYP_VAR_PREFIX))
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_java_constants":
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_var_prefix := $(GYP_VAR_PREFIX)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/java_cpp_enum.py $(LOCAL_PATH)/content/public/browser/invalidate_type.h $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating Java from cpp header public/browser/invalidate_type.h ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser; python ../build/android/gyp/java_cpp_enum.py "--output_dir=$(gyp_shared_intermediate_dir)/enums/invalidate_types_java" public/browser/invalidate_type.h
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+### Set directly by aosp_build_settings.
+LOCAL_CLANG := false
+LOCAL_NDK_STL_VARIANT := stlport_static
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_invalidate_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: invalidate_types_java
+invalidate_types_java: content_invalidate_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
+
+LOCAL_2ND_ARCH_VAR_PREFIX :=
diff --git a/content/invalidate_types_java.target.linux-x86.mk b/content/invalidate_types_java.target.linux-x86.mk
new file mode 100644
index 0000000..addab3e
--- /dev/null
+++ b/content/invalidate_types_java.target.linux-x86.mk
@@ -0,0 +1,59 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_invalidate_types_java_gyp
+LOCAL_MODULE_STEM := invalidate_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TARGET_ARCH := $(TARGET_$(GYP_VAR_PREFIX)ARCH)
+LOCAL_SDK_VERSION := 21
+gyp_intermediate_dir := $(call local-intermediates-dir,,$(GYP_VAR_PREFIX))
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_java_constants":
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_var_prefix := $(GYP_VAR_PREFIX)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/java_cpp_enum.py $(LOCAL_PATH)/content/public/browser/invalidate_type.h $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating Java from cpp header public/browser/invalidate_type.h ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser; python ../build/android/gyp/java_cpp_enum.py "--output_dir=$(gyp_shared_intermediate_dir)/enums/invalidate_types_java" public/browser/invalidate_type.h
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+### Set directly by aosp_build_settings.
+LOCAL_CLANG := false
+LOCAL_NDK_STL_VARIANT := stlport_static
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_invalidate_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: invalidate_types_java
+invalidate_types_java: content_invalidate_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
+
+LOCAL_2ND_ARCH_VAR_PREFIX :=
diff --git a/content/invalidate_types_java.target.linux-x86_64.mk b/content/invalidate_types_java.target.linux-x86_64.mk
new file mode 100644
index 0000000..addab3e
--- /dev/null
+++ b/content/invalidate_types_java.target.linux-x86_64.mk
@@ -0,0 +1,59 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_invalidate_types_java_gyp
+LOCAL_MODULE_STEM := invalidate_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TARGET_ARCH := $(TARGET_$(GYP_VAR_PREFIX)ARCH)
+LOCAL_SDK_VERSION := 21
+gyp_intermediate_dir := $(call local-intermediates-dir,,$(GYP_VAR_PREFIX))
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_java_constants":
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_var_prefix := $(GYP_VAR_PREFIX)
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/java_cpp_enum.py $(LOCAL_PATH)/content/public/browser/invalidate_type.h $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating Java from cpp header public/browser/invalidate_type.h ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser; python ../build/android/gyp/java_cpp_enum.py "--output_dir=$(gyp_shared_intermediate_dir)/enums/invalidate_types_java" public/browser/invalidate_type.h
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/enums/invalidate_types_java/org/chromium/content_public/browser/InvalidateTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+### Set directly by aosp_build_settings.
+LOCAL_CLANG := false
+LOCAL_NDK_STL_VARIANT := stlport_static
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_invalidate_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: invalidate_types_java
+invalidate_types_java: content_invalidate_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
+
+LOCAL_2ND_ARCH_VAR_PREFIX :=
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index 94bb878..92ca029 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -112,6 +112,7 @@
     "//content/browser/android/gesture_event_type.h",
     "//content/browser/renderer_host/input/selection_event_type.h",
     "//content/browser/gamepad/gamepad_standard_mappings.h",
+    "//content/public/browser/invalidate_type.h",
     "//content/public/common/result_codes.h",
     "//content/public/common/screen_orientation_values.h",
     "//content/public/common/speech_recognition_error.h",
@@ -123,6 +124,7 @@
     "org/chromium/content/browser/input/CanonicalButtonIndex.java",
     "org/chromium/content/browser/input/PopupItemType.java",
     "org/chromium/content/browser/input/SelectionEventType.java",
+    "org/chromium/content_public/browser/InvalidateTypes.java",
     "org/chromium/content_public/common/ResultCode.java",
     "org/chromium/content_public/common/ScreenOrientationValues.java",
     "org/chromium/content_public/common/SpeechRecognitionErrorCode.java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
index db7875b..d30b10c 100644
--- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -161,6 +161,11 @@
     }
 
     @Override
+    public String getLastCommittedUrl() {
+        return nativeGetLastCommittedURL(mNativeWebContentsAndroid);
+    }
+
+    @Override
     public boolean isIncognito() {
         return nativeIsIncognito(mNativeWebContentsAndroid);
     }
@@ -239,6 +244,11 @@
         nativeEvaluateJavaScript(mNativeWebContentsAndroid, script, callback);
     }
 
+    @Override
+    public boolean hasAccessedInitialDocument() {
+        return nativeHasAccessedInitialDocument(mNativeWebContentsAndroid);
+    }
+
     @CalledByNative
     private static void onEvaluateJavaScriptResult(
             String jsonResult, JavaScriptCallback callback) {
@@ -275,6 +285,7 @@
     private native void nativeScrollFocusedEditableNodeIntoView(long nativeWebContentsAndroid);
     private native void nativeSelectWordAroundCaret(long nativeWebContentsAndroid);
     private native String nativeGetURL(long nativeWebContentsAndroid);
+    private native String nativeGetLastCommittedURL(long nativeWebContentsAndroid);
     private native boolean nativeIsIncognito(long nativeWebContentsAndroid);
     private native void nativeResumeResponseDeferredAtStart(long nativeWebContentsAndroid);
     private native void nativeSetHasPendingNavigationTransitionForTesting(
@@ -288,4 +299,6 @@
             String script, JavaScriptCallback callback);
     private native void nativePostMessageToFrame(long nativeWebContentsAndroid, String frameId,
             String message, String sourceOrigin, String targetOrigin);
+    private native boolean nativeHasAccessedInitialDocument(
+            long nativeWebContentsAndroid);
 }
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
index dd835c7..d05bdc4 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
@@ -133,6 +133,14 @@
     public String getUrl();
 
     /**
+     * Gets the last committed URL. It represents the current page that is
+     * displayed in this WebContents. It represents the current security context.
+     *
+     * @return The last committed URL.
+     */
+    public String getLastCommittedUrl();
+
+    /**
      * Get the InCognito state of WebContents.
      *
      * @return whether this WebContents is in InCognito mode or not
@@ -194,4 +202,12 @@
      */
     public void postMessageToFrame(String frameName, String message,
             String sourceOrigin, String targetOrigin);
+
+    /**
+     * Returns whether the initial empty page has been accessed by a script from another
+     * page. Always false after the first commit.
+     *
+     * @return Whether the initial empty page has been accessed by a script.
+     */
+    public boolean hasAccessedInitialDocument();
 }
diff --git a/content/public/browser/invalidate_type.h b/content/public/browser/invalidate_type.h
index 975bb30..17040e1 100644
--- a/content/public/browser/invalidate_type.h
+++ b/content/public/browser/invalidate_type.h
@@ -9,6 +9,10 @@
 
 // Flags passed to the WebContentsDelegate.NavigationStateChanged to tell it
 // what has changed. Combine them to update more than one thing.
+//
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content_public.browser
+// GENERATED_JAVA_PREFIX_TO_STRIP: INVALIDATE_TYPE_
 enum InvalidateTypes {
   INVALIDATE_TYPE_URL           = 1 << 0,  // The URL has changed.
   INVALIDATE_TYPE_TAB           = 1 << 1,  // The favicon, app icon, or crashed
diff --git a/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java b/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
index 66a9bd9..9061281 100644
--- a/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
+++ b/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
@@ -80,11 +80,14 @@
         final boolean mIsRedirect;
         final Runnable mResponseAction;
         final boolean mIsNotFound;
+        final boolean mIsNoContent;
 
         Response(byte[] responseData, List<Pair<String, String>> responseHeaders,
-                boolean isRedirect, boolean isNotFound, Runnable responseAction) {
+                boolean isRedirect, boolean isNotFound, boolean isNoContent,
+                Runnable responseAction) {
             mIsRedirect = isRedirect;
             mIsNotFound = isNotFound;
+            mIsNoContent = isNoContent;
             mResponseData = responseData;
             mResponseHeaders = responseHeaders == null ?
                     new ArrayList<Pair<String, String>>() : responseHeaders;
@@ -208,6 +211,7 @@
     private static final int RESPONSE_STATUS_NORMAL = 0;
     private static final int RESPONSE_STATUS_MOVED_TEMPORARILY = 1;
     private static final int RESPONSE_STATUS_NOT_FOUND = 2;
+    private static final int RESPONSE_STATUS_NO_CONTENT = 3;
 
     private String setResponseInternal(
             String requestPath, byte[] responseData,
@@ -215,10 +219,12 @@
             int status) {
         final boolean isRedirect = (status == RESPONSE_STATUS_MOVED_TEMPORARILY);
         final boolean isNotFound = (status == RESPONSE_STATUS_NOT_FOUND);
+        final boolean isNoContent = (status == RESPONSE_STATUS_NO_CONTENT);
 
         synchronized (mLock) {
             mResponseMap.put(requestPath, new Response(
-                    responseData, responseHeaders, isRedirect, isNotFound, responseAction));
+                    responseData, responseHeaders, isRedirect, isNotFound, isNoContent,
+                    responseAction));
             mResponseCountMap.put(requestPath, Integer.valueOf(0));
             mLastRequestMap.put(requestPath, null);
         }
@@ -251,6 +257,18 @@
     }
 
     /**
+     * Sets a 204 (no content) response to be returned when a particular request path is passed in.
+     *
+     * @param requestPath The path to respond to.
+     * @return The full URL including the path that should be requested to get the expected
+     *         response.
+     */
+    public String setResponseWithNoContentStatus(String requestPath) {
+        return setResponseInternal(
+                requestPath, "".getBytes(), null, null, RESPONSE_STATUS_NO_CONTENT);
+    }
+
+    /**
      * Sets a response to be returned when a particular request path is passed
      * in (with the option to specify additional headers).
      *
@@ -451,6 +469,10 @@
         } else if (response.mIsNotFound) {
             httpResponse = createResponse(HttpStatus.SC_NOT_FOUND);
             servedResponseFor(path, request);
+        } else if (response.mIsNoContent) {
+            httpResponse = createResponse(HttpStatus.SC_NO_CONTENT);
+            httpResponse.setHeader("Content-Length", "0");
+            servedResponseFor(path, request);
         } else if (response.mIsRedirect) {
             httpResponse = createResponse(HttpStatus.SC_MOVED_TEMPORARILY);
             for (Pair<String, String> header : response.mResponseHeaders) {