AwWebContentsDelegateAdapter.java revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
1// Copyright 2013 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.os.Handler; 9import android.os.Looper; 10import android.os.Message; 11import android.util.Log; 12import android.view.KeyEvent; 13import android.view.View; 14import android.webkit.ConsoleMessage; 15import android.webkit.ValueCallback; 16 17import org.chromium.content.browser.ContentViewCore; 18 19/** 20 * Adapts the AwWebContentsDelegate interface to the AwContentsClient interface. 21 * This class also serves a secondary function of routing certain callbacks from the content layer 22 * to specific listener interfaces. 23 */ 24class AwWebContentsDelegateAdapter extends AwWebContentsDelegate { 25 private static final String TAG = "AwWebContentsDelegateAdapter"; 26 27 final AwContentsClient mContentsClient; 28 final View mContainerView; 29 30 public AwWebContentsDelegateAdapter(AwContentsClient contentsClient, 31 View containerView) { 32 mContentsClient = contentsClient; 33 mContainerView = containerView; 34 } 35 36 @Override 37 public void onLoadProgressChanged(int progress) { 38 mContentsClient.onProgressChanged(progress); 39 } 40 41 @Override 42 public void handleKeyboardEvent(KeyEvent event) { 43 if (event.getAction() == KeyEvent.ACTION_DOWN) { 44 int direction; 45 switch (event.getKeyCode()) { 46 case KeyEvent.KEYCODE_DPAD_DOWN: 47 direction = View.FOCUS_DOWN; 48 break; 49 case KeyEvent.KEYCODE_DPAD_UP: 50 direction = View.FOCUS_UP; 51 break; 52 case KeyEvent.KEYCODE_DPAD_LEFT: 53 direction = View.FOCUS_LEFT; 54 break; 55 case KeyEvent.KEYCODE_DPAD_RIGHT: 56 direction = View.FOCUS_RIGHT; 57 break; 58 default: 59 direction = 0; 60 break; 61 } 62 if (direction != 0 && tryToMoveFocus(direction)) return; 63 } 64 mContentsClient.onUnhandledKeyEvent(event); 65 } 66 67 @Override 68 public boolean takeFocus(boolean reverse) { 69 int direction = 70 (reverse == (mContainerView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL)) ? 71 View.FOCUS_RIGHT : View.FOCUS_LEFT; 72 if (tryToMoveFocus(direction)) return true; 73 direction = reverse ? View.FOCUS_UP : View.FOCUS_DOWN; 74 return tryToMoveFocus(direction); 75 } 76 77 private boolean tryToMoveFocus(int direction) { 78 View focus = mContainerView.focusSearch(direction); 79 return focus != null && focus != mContainerView && focus.requestFocus(); 80 } 81 82 @Override 83 public boolean addMessageToConsole(int level, String message, int lineNumber, 84 String sourceId) { 85 ConsoleMessage.MessageLevel messageLevel = ConsoleMessage.MessageLevel.DEBUG; 86 switch(level) { 87 case LOG_LEVEL_TIP: 88 messageLevel = ConsoleMessage.MessageLevel.TIP; 89 break; 90 case LOG_LEVEL_LOG: 91 messageLevel = ConsoleMessage.MessageLevel.LOG; 92 break; 93 case LOG_LEVEL_WARNING: 94 messageLevel = ConsoleMessage.MessageLevel.WARNING; 95 break; 96 case LOG_LEVEL_ERROR: 97 messageLevel = ConsoleMessage.MessageLevel.ERROR; 98 break; 99 default: 100 Log.w(TAG, "Unknown message level, defaulting to DEBUG"); 101 break; 102 } 103 104 return mContentsClient.onConsoleMessage( 105 new ConsoleMessage(message, sourceId, lineNumber, messageLevel)); 106 } 107 108 @Override 109 public void onUpdateUrl(String url) { 110 // TODO: implement 111 } 112 113 @Override 114 public void openNewTab(String url, String extraHeaders, byte[] postData, int disposition) { 115 // This is only called in chrome layers. 116 assert false; 117 } 118 119 @Override 120 public void closeContents() { 121 mContentsClient.onCloseWindow(); 122 } 123 124 @Override 125 public void showRepostFormWarningDialog(final ContentViewCore contentViewCore) { 126 // TODO(mkosiba) We should be using something akin to the JsResultReceiver as the 127 // callback parameter (instead of ContentViewCore) and implement a way of converting 128 // that to a pair of messages. 129 final int MSG_CONTINUE_PENDING_RELOAD = 1; 130 final int MSG_CANCEL_PENDING_RELOAD = 2; 131 132 // TODO(sgurun) Remember the URL to cancel the reload behavior 133 // if it is different than the most recent NavigationController entry. 134 final Handler handler = new Handler(Looper.getMainLooper()) { 135 @Override 136 public void handleMessage(Message msg) { 137 switch(msg.what) { 138 case MSG_CONTINUE_PENDING_RELOAD: { 139 contentViewCore.continuePendingReload(); 140 break; 141 } 142 case MSG_CANCEL_PENDING_RELOAD: { 143 contentViewCore.cancelPendingReload(); 144 break; 145 } 146 default: 147 throw new IllegalStateException( 148 "WebContentsDelegateAdapter: unhandled message " + msg.what); 149 } 150 } 151 }; 152 153 Message resend = handler.obtainMessage(MSG_CONTINUE_PENDING_RELOAD); 154 Message dontResend = handler.obtainMessage(MSG_CANCEL_PENDING_RELOAD); 155 mContentsClient.onFormResubmission(dontResend, resend); 156 } 157 158 @Override 159 public void runFileChooser(final int processId, final int renderId, final int mode_flags, 160 String acceptTypes, String title, String defaultFilename, boolean capture) { 161 AwContentsClient.FileChooserParams params = new AwContentsClient.FileChooserParams(); 162 params.mode = mode_flags; 163 params.acceptTypes = acceptTypes; 164 params.title = title; 165 params.defaultFilename = defaultFilename; 166 params.capture = capture; 167 168 mContentsClient.showFileChooser(new ValueCallback<String[]>() { 169 boolean completed = false; 170 @Override 171 public void onReceiveValue(String[] results) { 172 if (completed) { 173 throw new IllegalStateException("Duplicate showFileChooser result"); 174 } 175 completed = true; 176 nativeFilesSelectedInChooser(processId, renderId, mode_flags, results); 177 } 178 }, params); 179 } 180 181 @Override 182 public boolean addNewContents(boolean isDialog, boolean isUserGesture) { 183 return mContentsClient.onCreateWindow(isDialog, isUserGesture); 184 } 185 186 @Override 187 public void activateContents() { 188 mContentsClient.onRequestFocus(); 189 } 190} 191