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.graphics.Rect; |
8 | import android.os.Handler; |
9 | import android.os.Looper; |
10 | import android.os.Message; |
11 | import android.util.Log; |
12 | import android.view.KeyEvent; |
13 | import android.webkit.ConsoleMessage; |
14 | import android.webkit.ValueCallback; |
15 | |
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 | /** |
27 | * Listener definition for a callback to be invoked when the preferred size of the page |
28 | * contents changes. |
29 | */ |
30 | public interface PreferredSizeChangedListener { |
31 | /** |
32 | * Called when the preferred size of the page contents changes. |
33 | * @see AwWebContentsDelegate#updatePreferredSize |
34 | */ |
35 | void updatePreferredSize(int width, int height); |
36 | } |
37 | |
38 | final AwContentsClient mContentsClient; |
39 | final PreferredSizeChangedListener mPreferredSizeChangedListener; |
40 | |
41 | public AwWebContentsDelegateAdapter(AwContentsClient contentsClient, |
42 | PreferredSizeChangedListener preferredSizeChangedListener) { |
43 | mContentsClient = contentsClient; |
44 | mPreferredSizeChangedListener = preferredSizeChangedListener; |
45 | } |
46 | |
47 | @Override |
48 | public void onLoadProgressChanged(int progress) { |
49 | mContentsClient.onProgressChanged(progress); |
50 | } |
51 | |
52 | @Override |
53 | public void handleKeyboardEvent(KeyEvent event) { |
54 | mContentsClient.onUnhandledKeyEvent(event); |
55 | } |
56 | |
57 | @Override |
58 | public boolean addMessageToConsole(int level, String message, int lineNumber, |
59 | String sourceId) { |
60 | ConsoleMessage.MessageLevel messageLevel = ConsoleMessage.MessageLevel.DEBUG; |
61 | switch(level) { |
62 | case LOG_LEVEL_TIP: |
63 | messageLevel = ConsoleMessage.MessageLevel.TIP; |
64 | break; |
65 | case LOG_LEVEL_LOG: |
66 | messageLevel = ConsoleMessage.MessageLevel.LOG; |
67 | break; |
68 | case LOG_LEVEL_WARNING: |
69 | messageLevel = ConsoleMessage.MessageLevel.WARNING; |
70 | break; |
71 | case LOG_LEVEL_ERROR: |
72 | messageLevel = ConsoleMessage.MessageLevel.ERROR; |
73 | break; |
74 | default: |
75 | Log.w(TAG, "Unknown message level, defaulting to DEBUG"); |
76 | break; |
77 | } |
78 | |
79 | return mContentsClient.onConsoleMessage( |
80 | new ConsoleMessage(message, sourceId, lineNumber, messageLevel)); |
81 | } |
82 | |
83 | @Override |
84 | public void onUpdateUrl(String url) { |
85 | // TODO: implement |
86 | } |
87 | |
88 | @Override |
89 | public void openNewTab(String url, String extraHeaders, byte[] postData, int disposition) { |
90 | // This is only called in chrome layers. |
91 | assert false; |
92 | } |
93 | |
94 | @Override |
95 | public boolean addNewContents(int nativeSourceWebContents, int nativeWebContents, |
96 | int disposition, Rect initialPosition, boolean userGesture) { |
97 | // This is overridden native side; see the other addNewContents overload. |
98 | throw new RuntimeException("Impossible"); |
99 | } |
100 | |
101 | @Override |
102 | public void closeContents() { |
103 | mContentsClient.onCloseWindow(); |
104 | } |
105 | |
106 | @Override |
107 | public void showRepostFormWarningDialog(final ContentViewCore contentViewCore) { |
108 | // TODO(mkosiba) We should be using something akin to the JsResultReceiver as the |
109 | // callback parameter (instead of ContentViewCore) and implement a way of converting |
110 | // that to a pair of messages. |
111 | final int MSG_CONTINUE_PENDING_RELOAD = 1; |
112 | final int MSG_CANCEL_PENDING_RELOAD = 2; |
113 | |
114 | // TODO(sgurun) Remember the URL to cancel the reload behavior |
115 | // if it is different than the most recent NavigationController entry. |
116 | final Handler handler = new Handler(Looper.getMainLooper()) { |
117 | @Override |
118 | public void handleMessage(Message msg) { |
119 | switch(msg.what) { |
120 | case MSG_CONTINUE_PENDING_RELOAD: { |
121 | contentViewCore.continuePendingReload(); |
122 | break; |
123 | } |
124 | case MSG_CANCEL_PENDING_RELOAD: { |
125 | contentViewCore.cancelPendingReload(); |
126 | break; |
127 | } |
128 | default: |
129 | throw new IllegalStateException( |
130 | "WebContentsDelegateAdapter: unhandled message " + msg.what); |
131 | } |
132 | } |
133 | }; |
134 | |
135 | Message resend = handler.obtainMessage(MSG_CONTINUE_PENDING_RELOAD); |
136 | Message dontResend = handler.obtainMessage(MSG_CANCEL_PENDING_RELOAD); |
137 | mContentsClient.onFormResubmission(dontResend, resend); |
138 | } |
139 | |
140 | @Override |
141 | public void runFileChooser(final int processId, final int renderId, final int mode_flags, |
142 | String acceptTypes, String title, String defaultFilename, boolean capture) { |
143 | AwContentsClient.FileChooserParams params = new AwContentsClient.FileChooserParams(); |
144 | params.mode = mode_flags; |
145 | params.acceptTypes = acceptTypes; |
146 | params.title = title; |
147 | params.defaultFilename = defaultFilename; |
148 | params.capture = capture; |
149 | |
150 | mContentsClient.showFileChooser(new ValueCallback<String[]>() { |
151 | boolean completed = false; |
152 | @Override |
153 | public void onReceiveValue(String[] results) { |
154 | if (completed) { |
155 | throw new IllegalStateException("Duplicate showFileChooser result"); |
156 | } |
157 | completed = true; |
158 | nativeFilesSelectedInChooser(processId, renderId, mode_flags, results); |
159 | } |
160 | }, params); |
161 | } |
162 | |
163 | @Override |
164 | public boolean addNewContents(boolean isDialog, boolean isUserGesture) { |
165 | return mContentsClient.onCreateWindow(isDialog, isUserGesture); |
166 | } |
167 | |
168 | @Override |
169 | public void activateContents() { |
170 | mContentsClient.onRequestFocus(); |
171 | } |
172 | |
173 | @Override |
174 | public void updatePreferredSize(int width, int height) { |
175 | mPreferredSizeChangedListener.updatePreferredSize(width, height); |
176 | } |
177 | } |