1 // Copyright 2019 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.content_public.browser; 6 7 import androidx.annotation.NonNull; 8 9 import org.chromium.base.annotations.CalledByNative; 10 import org.chromium.base.annotations.JNINamespace; 11 import org.chromium.base.annotations.NativeMethods; 12 import org.chromium.net.NetError; 13 import org.chromium.url.GURL; 14 15 /** 16 * JNI bridge with content::NavigationHandle 17 */ 18 @JNINamespace("content") 19 public class NavigationHandle { 20 private long mNativeNavigationHandleProxy; 21 private final boolean mIsInMainFrame; 22 private final boolean mIsRendererInitiated; 23 private final boolean mIsSameDocument; 24 private Integer mPageTransition; 25 private GURL mUrl; 26 private boolean mHasCommitted; 27 private boolean mIsDownload; 28 private boolean mIsErrorPage; 29 private boolean mIsFragmentNavigation; 30 private boolean mIsValidSearchFormUrl; 31 private @NetError int mErrorCode; 32 private int mHttpStatusCode; 33 34 @CalledByNative NavigationHandle(long nativeNavigationHandleProxy, GURL url, boolean isInMainFrame, boolean isSameDocument, boolean isRendererInitiated)35 public NavigationHandle(long nativeNavigationHandleProxy, GURL url, boolean isInMainFrame, 36 boolean isSameDocument, boolean isRendererInitiated) { 37 mNativeNavigationHandleProxy = nativeNavigationHandleProxy; 38 mUrl = url; 39 mIsInMainFrame = isInMainFrame; 40 mIsSameDocument = isSameDocument; 41 mIsRendererInitiated = isRendererInitiated; 42 } 43 44 /** 45 * The navigation received a redirect. Called once per redirect. 46 * @param url The new URL. 47 */ 48 @CalledByNative didRedirect(GURL url)49 private void didRedirect(GURL url) { 50 mUrl = url; 51 } 52 53 /** 54 * The navigation finished. Called once per navigation. 55 */ 56 @CalledByNative didFinish(@onNull GURL url, boolean isErrorPage, boolean hasCommitted, boolean isFragmentNavigation, boolean isDownload, boolean isValidSearchFormUrl, int transition, @NetError int errorCode, int httpStatuscode)57 public void didFinish(@NonNull GURL url, boolean isErrorPage, boolean hasCommitted, 58 boolean isFragmentNavigation, boolean isDownload, boolean isValidSearchFormUrl, 59 int transition, @NetError int errorCode, int httpStatuscode) { 60 mUrl = url; 61 mIsErrorPage = isErrorPage; 62 mHasCommitted = hasCommitted; 63 mIsFragmentNavigation = isFragmentNavigation; 64 mIsDownload = isDownload; 65 mIsValidSearchFormUrl = isValidSearchFormUrl; 66 mPageTransition = transition == -1 ? null : transition; 67 mErrorCode = errorCode; 68 mHttpStatusCode = httpStatuscode; 69 } 70 71 /** 72 * Release the C++ pointer. 73 */ 74 @CalledByNative release()75 private void release() { 76 mNativeNavigationHandleProxy = 0; 77 } 78 nativePtr()79 public long nativePtr() { 80 return mNativeNavigationHandleProxy; 81 } 82 83 /** 84 * The URL the frame is navigating to. This may change during the navigation when encountering 85 * a server redirect. 86 * 87 * @deprecated Please use {@link #getUrl} instead. 88 */ 89 @Deprecated getUrlString()90 public String getUrlString() { 91 return mUrl.getPossiblyInvalidSpec(); 92 } 93 94 /** 95 * The URL the frame is navigating to. This may change during the navigation when encountering 96 * a server redirect. 97 */ getUrl()98 public GURL getUrl() { 99 return mUrl; 100 } 101 102 /** 103 * Whether the navigation is taking place in the main frame or in a subframe. 104 */ isInMainFrame()105 public boolean isInMainFrame() { 106 return mIsInMainFrame; 107 } 108 109 /** 110 * Whether the navigation was initiated by the renderer process. Examples of renderer-initiated 111 * navigations include: 112 * - <a> link click 113 * - changing window.location.href 114 * - redirect via the <meta http-equiv="refresh"> tag 115 * - using window.history.pushState 116 * 117 * This method returns false for browser-initiated navigations, including: 118 * - any navigation initiated from the omnibox 119 * - navigations via suggestions in browser UI 120 * - navigations via browser UI: Ctrl-R, refresh/forward/back/home buttons 121 * - using window.history.forward() or window.history.back() 122 * - any other "explicit" URL navigations, e.g. bookmarks 123 */ isRendererInitiated()124 public boolean isRendererInitiated() { 125 return mIsRendererInitiated; 126 } 127 128 /** 129 * Whether the navigation happened without changing document. 130 * Examples of same document navigations are: 131 * - reference fragment navigations 132 * - pushState/replaceState 133 * - same page history navigation 134 */ isSameDocument()135 public boolean isSameDocument() { 136 return mIsSameDocument; 137 } 138 errorDescription()139 public String errorDescription() { 140 // TODO(shaktisahu): Provide appropriate error description (crbug/690784). 141 return ""; 142 } 143 errorCode()144 public @NetError int errorCode() { 145 return mErrorCode; 146 } 147 148 /** 149 * Whether the navigation has committed. Navigations that end up being downloads or return 150 * 204/205 response codes do not commit (i.e. the WebContents stays at the existing URL). This 151 * returns true for either successful commits or error pages that replace the previous page 152 * (distinguished by |IsErrorPage|), and false for errors that leave the user on the previous 153 * page. 154 */ hasCommitted()155 public boolean hasCommitted() { 156 return mHasCommitted; 157 } 158 159 /** 160 * Return the HTTP status code. This can be used after the response is received in 161 * didFinishNavigation() 162 */ httpStatusCode()163 public int httpStatusCode() { 164 return mHttpStatusCode; 165 } 166 167 /** 168 * Returns the page transition type. 169 */ pageTransition()170 public Integer pageTransition() { 171 return mPageTransition; 172 } 173 174 /** 175 * Returns true on same-document navigation with fragment change. 176 */ isFragmentNavigation()177 public boolean isFragmentNavigation() { 178 return mIsFragmentNavigation; 179 } 180 181 /** 182 * Whether the navigation resulted in an error page. 183 * Note that if an error page reloads, this will return true even though GetNetErrorCode will be 184 * net::OK. 185 */ isErrorPage()186 public boolean isErrorPage() { 187 return mIsErrorPage; 188 } 189 190 /** 191 * Returns true if this navigation resulted in a download. Returns false if this navigation did 192 * not result in a download, or if download status is not yet known for this navigation. 193 * Download status is determined for a navigation when processing final (post redirect) HTTP 194 * response headers. 195 */ isDownload()196 public boolean isDownload() { 197 return mIsDownload; 198 } 199 200 /** 201 * Returns true if the navigation is a search. 202 */ isValidSearchFormUrl()203 public boolean isValidSearchFormUrl() { 204 return mIsValidSearchFormUrl; 205 } 206 207 /** 208 * Set request's header. If the header is already present, its value is overwritten. When 209 * modified during a navigation start, the headers will be applied to the initial network 210 * request. When modified during a redirect, the headers will be applied to the redirected 211 * request. 212 */ setRequestHeader(String headerName, String headerValue)213 public void setRequestHeader(String headerName, String headerValue) { 214 NavigationHandleJni.get().setRequestHeader( 215 mNativeNavigationHandleProxy, headerName, headerValue); 216 } 217 218 /** 219 * Remove a request's header. If the header is not present, it has no effect. Must be called 220 * during a redirect. 221 */ removeRequestHeader(String headerName)222 public void removeRequestHeader(String headerName) { 223 NavigationHandleJni.get().removeRequestHeader(mNativeNavigationHandleProxy, headerName); 224 } 225 226 @NativeMethods 227 interface Natives { setRequestHeader( long nativeNavigationHandleProxy, String headerName, String headerValue)228 void setRequestHeader( 229 long nativeNavigationHandleProxy, String headerName, String headerValue); removeRequestHeader(long nativeNavigationHandleProxy, String headerName)230 void removeRequestHeader(long nativeNavigationHandleProxy, String headerName); 231 } 232 } 233