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