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