AwContentsClient.java revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 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 5package org.chromium.android_webview; 6 7import android.graphics.Rect; 8import android.graphics.RectF; 9import android.os.Handler; 10import android.os.Looper; 11import android.os.Message; 12import android.util.Log; 13import android.view.KeyEvent; 14import android.webkit.ConsoleMessage; 15 16import org.chromium.content.browser.ContentViewClient; 17import org.chromium.content.browser.ContentViewCore; 18import org.chromium.content.browser.WebContentsObserverAndroid; 19import org.chromium.net.NetError; 20 21/** 22 * Base-class that an AwContents embedder derives from to receive callbacks. 23 * This extends ContentViewClient, as in many cases we want to pass-thru ContentViewCore 24 * callbacks right to our embedder, and this setup facilities that. 25 * For any other callbacks we need to make transformations of (e.g. adapt parameters 26 * or perform filtering) we can provide final overrides for methods here, and then introduce 27 * new abstract methods that the our own client must implement. 28 * i.e.: all methods in this class should either be final, or abstract. 29 */ 30public abstract class AwContentsClient extends ContentViewClient { 31 32 private static final String TAG = "AwContentsClient"; 33 // Handler for WebContentsDelegate callbacks 34 private final WebContentsDelegateAdapter mWebContentsDelegateAdapter = 35 new WebContentsDelegateAdapter(); 36 37 private AwWebContentsObserver mWebContentsObserver; 38 39 //-------------------------------------------------------------------------------------------- 40 // Adapter for WebContentsDelegate methods. 41 //-------------------------------------------------------------------------------------------- 42 43 class WebContentsDelegateAdapter extends AwWebContentsDelegate { 44 45 // The message ids. 46 public final static int CONTINUE_PENDING_RELOAD = 1; 47 public final static int CANCEL_PENDING_RELOAD = 2; 48 49 // Handler associated with this adapter. 50 // TODO(sgurun) Remember the URL to cancel the resend behavior 51 // if it is different than the most recent NavigationController entry. 52 private final Handler mHandler = new Handler(Looper.getMainLooper()) { 53 54 @Override 55 public void handleMessage(Message msg) { 56 switch (msg.what) { 57 case CONTINUE_PENDING_RELOAD: 58 ((ContentViewCore) msg.obj).continuePendingReload(); 59 break; 60 case CANCEL_PENDING_RELOAD: 61 ((ContentViewCore) msg.obj).cancelPendingReload(); 62 break; 63 default: 64 Log.w(TAG, "Unknown message " + msg.what); 65 break; 66 } 67 } 68 }; 69 70 @Override 71 public void onLoadProgressChanged(int progress) { 72 AwContentsClient.this.onProgressChanged(progress); 73 } 74 75 @Override 76 public void handleKeyboardEvent(KeyEvent event) { 77 AwContentsClient.this.onUnhandledKeyEvent(event); 78 } 79 80 @Override 81 public boolean addMessageToConsole(int level, String message, int lineNumber, 82 String sourceId) { 83 ConsoleMessage.MessageLevel messageLevel = ConsoleMessage.MessageLevel.DEBUG; 84 switch(level) { 85 case LOG_LEVEL_TIP: 86 messageLevel = ConsoleMessage.MessageLevel.TIP; 87 break; 88 case LOG_LEVEL_LOG: 89 messageLevel = ConsoleMessage.MessageLevel.LOG; 90 break; 91 case LOG_LEVEL_WARNING: 92 messageLevel = ConsoleMessage.MessageLevel.WARNING; 93 break; 94 case LOG_LEVEL_ERROR: 95 messageLevel = ConsoleMessage.MessageLevel.ERROR; 96 break; 97 default: 98 Log.w(TAG, "Unknown message level, defaulting to DEBUG"); 99 break; 100 } 101 102 return AwContentsClient.this.onConsoleMessage( 103 new ConsoleMessage(message, sourceId, lineNumber, messageLevel)); 104 } 105 106 @Override 107 public void onUpdateUrl(String url) { 108 // TODO: implement 109 } 110 111 @Override 112 public void openNewTab(String url, boolean incognito) { 113 // TODO: implement 114 } 115 116 @Override 117 public boolean addNewContents(int nativeSourceWebContents, int nativeWebContents, 118 int disposition, Rect initialPosition, boolean userGesture) { 119 // TODO: implement 120 return false; 121 } 122 123 @Override 124 public void closeContents() { 125 // TODO: implement 126 } 127 128 @Override 129 public void onUrlStarredChanged(boolean starred) { 130 // TODO: implement 131 } 132 133 @Override 134 public void showRepostFormWarningDialog(ContentViewCore contentViewCore) { 135 Message dontResend = mHandler.obtainMessage(CANCEL_PENDING_RELOAD, contentViewCore); 136 Message resend = mHandler.obtainMessage(CONTINUE_PENDING_RELOAD, contentViewCore); 137 AwContentsClient.this.onFormResubmission(dontResend, resend); 138 } 139 } 140 141 class AwWebContentsObserver extends WebContentsObserverAndroid { 142 public AwWebContentsObserver(ContentViewCore contentViewCore) { 143 super(contentViewCore); 144 } 145 146 @Override 147 public void didStartLoading(String url) { 148 AwContentsClient.this.onPageStarted(url); 149 } 150 151 @Override 152 public void didStopLoading(String url) { 153 AwContentsClient.this.onPageFinished(url); 154 } 155 156 @Override 157 public void didFailLoad(boolean isProvisionalLoad, 158 boolean isMainFrame, int errorCode, String description, String failingUrl) { 159 if (errorCode == NetError.ERR_ABORTED) { 160 // This error code is generated for the following reasons: 161 // - WebView.stopLoading is called, 162 // - the navigation is intercepted by the embedder via shouldIgnoreNavigation. 163 // 164 // The Android WebView does not notify the embedder of these situations using this 165 // error code with the WebViewClient.onReceivedError callback. 166 return; 167 } 168 if (!isMainFrame) { 169 // The Android WebView does not notify the embedder of sub-frame failures. 170 return; 171 } 172 AwContentsClient.this.onReceivedError( 173 ErrorCodeConversionHelper.convertErrorCode(errorCode), description, failingUrl); 174 } 175 } 176 177 void installWebContentsObserver(ContentViewCore contentViewCore) { 178 assert mWebContentsObserver == null; 179 mWebContentsObserver = new AwWebContentsObserver(contentViewCore); 180 } 181 182 final AwWebContentsDelegate getWebContentsDelegate() { 183 return mWebContentsDelegateAdapter; 184 } 185 186 //-------------------------------------------------------------------------------------------- 187 // WebView specific methods that map directly to WebViewClient / WebChromeClient 188 //-------------------------------------------------------------------------------------------- 189 // 190 191 public abstract void onProgressChanged(int progress); 192 193 public abstract InterceptedRequestData shouldInterceptRequest(String url); 194 195 public abstract void onLoadResource(String url); 196 197 public abstract boolean shouldIgnoreNavigation(String url); 198 199 public abstract void onUnhandledKeyEvent(KeyEvent event); 200 201 public abstract boolean onConsoleMessage(ConsoleMessage consoleMessage); 202 203 public abstract void onReceivedHttpAuthRequest(AwHttpAuthHandler handler, 204 String host, String realm); 205 206 public abstract void onFormResubmission(Message dontResend, Message resend); 207 208 protected abstract void handleJsAlert(String url, String message, JsResultReceiver receiver); 209 210 protected abstract void handleJsBeforeUnload(String url, String message, 211 JsResultReceiver receiver); 212 213 protected abstract void handleJsConfirm(String url, String message, JsResultReceiver receiver); 214 215 protected abstract void handleJsPrompt(String url, String message, String defaultValue, 216 JsPromptResultReceiver receiver); 217 218 //-------------------------------------------------------------------------------------------- 219 // Other WebView-specific methods 220 //-------------------------------------------------------------------------------------------- 221 // 222 223 public abstract void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches, 224 boolean isDoneCounting); 225 226 public abstract void onPageStarted(String url); 227 228 public abstract void onPageFinished(String url); 229 230 public abstract void onReceivedError(int errorCode, String description, String failingUrl); 231 232 //-------------------------------------------------------------------------------------------- 233 // Stuff that we ignore since it only makes sense for Chrome browser 234 //-------------------------------------------------------------------------------------------- 235 // 236 237 @Override 238 final public boolean shouldOverrideScroll(float dx, float dy, float scrollX, float scrollY) { 239 return false; 240 } 241 242 @Override 243 final public void onContextualActionBarShown() { 244 } 245 246 @Override 247 final public void onContextualActionBarHidden() { 248 } 249} 250