1// Copyright 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.content.pm.ActivityInfo;
8import android.graphics.Bitmap;
9import android.graphics.Picture;
10import android.net.http.SslError;
11import android.os.Looper;
12import android.os.Message;
13import android.view.KeyEvent;
14import android.view.View;
15import android.webkit.ConsoleMessage;
16import android.webkit.GeolocationPermissions;
17import android.webkit.ValueCallback;
18import android.webkit.WebChromeClient;
19
20import org.chromium.android_webview.permission.AwPermissionRequest;
21
22import java.security.Principal;
23import java.util.HashMap;
24
25/**
26 * Base-class that an AwContents embedder derives from to receive callbacks.
27 * This extends ContentViewClient, as in many cases we want to pass-thru ContentViewCore
28 * callbacks right to our embedder, and this setup facilities that.
29 * For any other callbacks we need to make transformations of (e.g. adapt parameters
30 * or perform filtering) we can provide final overrides for methods here, and then introduce
31 * new abstract methods that the our own client must implement.
32 * i.e.: all methods in this class should either be final, or abstract.
33 */
34public abstract class AwContentsClient {
35
36    private final AwContentsClientCallbackHelper mCallbackHelper;
37
38    // Last background color reported from the renderer. Holds the sentinal value INVALID_COLOR
39    // if not valid.
40    private int mCachedRendererBackgroundColor = INVALID_COLOR;
41
42    private static final int INVALID_COLOR = 0;
43
44    public AwContentsClient() {
45        this(Looper.myLooper());
46    }
47
48    // Alllow injection of the callback thread, for testing.
49    public AwContentsClient(Looper looper) {
50        mCallbackHelper = new AwContentsClientCallbackHelper(looper, this);
51    }
52
53    final AwContentsClientCallbackHelper getCallbackHelper() {
54        return mCallbackHelper;
55    }
56
57    final int getCachedRendererBackgroundColor() {
58        assert isCachedRendererBackgroundColorValid();
59        return mCachedRendererBackgroundColor;
60    }
61
62    final boolean isCachedRendererBackgroundColorValid() {
63        return mCachedRendererBackgroundColor != INVALID_COLOR;
64    }
65
66    final void onBackgroundColorChanged(int color) {
67        // Avoid storing the sentinal INVALID_COLOR (note that both 0 and 1 are both
68        // fully transparent so this transpose makes no visible difference).
69        mCachedRendererBackgroundColor = color == INVALID_COLOR ? 1 : color;
70    }
71
72    //--------------------------------------------------------------------------------------------
73    //             WebView specific methods that map directly to WebViewClient / WebChromeClient
74    //--------------------------------------------------------------------------------------------
75
76    /**
77     * Parameters for the {@link AwContentsClient#showFileChooser} method.
78     */
79    public static class FileChooserParams {
80        public int mode;
81        public String acceptTypes;
82        public String title;
83        public String defaultFilename;
84        public boolean capture;
85    }
86
87    /**
88     * Parameters for the {@link AwContentsClient#shouldInterceptRequest} method.
89     */
90    public static class ShouldInterceptRequestParams {
91        // Url of the request.
92        public String url;
93        // Is this for the main frame or a child iframe?
94        public boolean isMainFrame;
95        // Was a gesture associated with the request? Don't trust can easily be spoofed.
96        public boolean hasUserGesture;
97        // Method used (GET/POST/OPTIONS)
98        public String method;
99        // Headers that would have been sent to server.
100        public HashMap<String, String> requestHeaders;
101    }
102
103    public abstract void getVisitedHistory(ValueCallback<String[]> callback);
104
105    public abstract void doUpdateVisitedHistory(String url, boolean isReload);
106
107    public abstract void onProgressChanged(int progress);
108
109    public abstract AwWebResourceResponse shouldInterceptRequest(
110            ShouldInterceptRequestParams params);
111
112    public abstract boolean shouldOverrideKeyEvent(KeyEvent event);
113
114    public abstract boolean shouldOverrideUrlLoading(String url);
115
116    public abstract void onLoadResource(String url);
117
118    public abstract void onUnhandledKeyEvent(KeyEvent event);
119
120    public abstract boolean onConsoleMessage(ConsoleMessage consoleMessage);
121
122    public abstract void onReceivedHttpAuthRequest(AwHttpAuthHandler handler,
123            String host, String realm);
124
125    public abstract void onReceivedSslError(ValueCallback<Boolean> callback, SslError error);
126
127    // TODO(sgurun): Make abstract once this has rolled in downstream.
128    public void onReceivedClientCertRequest(
129            final AwContentsClientBridge.ClientCertificateRequestCallback callback,
130            final String[] keyTypes, final Principal[] principals, final String host,
131            final int port) { }
132
133    public abstract void onReceivedLoginRequest(String realm, String account, String args);
134
135    public abstract void onFormResubmission(Message dontResend, Message resend);
136
137    public abstract void onDownloadStart(String url, String userAgent, String contentDisposition,
138            String mimeType, long contentLength);
139
140    // TODO(joth): Make abstract once this has rolled in downstream.
141    public /*abstract*/ void showFileChooser(ValueCallback<String[]> uploadFilePathsCallback,
142            FileChooserParams fileChooserParams) { }
143
144    public abstract void onGeolocationPermissionsShowPrompt(String origin,
145            GeolocationPermissions.Callback callback);
146
147    public abstract void onGeolocationPermissionsHidePrompt();
148
149    // TODO(michaelbai): Change the abstract once merged
150    public /*abstract*/ void onPermissionRequest(AwPermissionRequest awPermissionRequest) {}
151
152    // TODO(michaelbai): Change the abstract once merged
153    public /*abstract*/ void onPermissionRequestCanceled(
154            AwPermissionRequest awPermissionRequest) {}
155
156    public abstract void onScaleChangedScaled(float oldScale, float newScale);
157
158    protected abstract void handleJsAlert(String url, String message, JsResultReceiver receiver);
159
160    protected abstract void handleJsBeforeUnload(String url, String message,
161            JsResultReceiver receiver);
162
163    protected abstract void handleJsConfirm(String url, String message, JsResultReceiver receiver);
164
165    protected abstract void handleJsPrompt(String url, String message, String defaultValue,
166            JsPromptResultReceiver receiver);
167
168    protected abstract boolean onCreateWindow(boolean isDialog, boolean isUserGesture);
169
170    protected abstract void onCloseWindow();
171
172    public abstract void onReceivedTouchIconUrl(String url, boolean precomposed);
173
174    public abstract void onReceivedIcon(Bitmap bitmap);
175
176    public abstract void onReceivedTitle(String title);
177
178    protected abstract void onRequestFocus();
179
180    protected abstract View getVideoLoadingProgressView();
181
182    public abstract void onPageStarted(String url);
183
184    public abstract void onPageFinished(String url);
185
186    public abstract void onReceivedError(int errorCode, String description, String failingUrl);
187
188    // TODO (michaelbai): Remove this method once the same method remove from
189    // WebViewContentsClientAdapter.
190    public void onShowCustomView(View view,
191           int requestedOrientation, WebChromeClient.CustomViewCallback callback) {
192    }
193
194    // TODO (michaelbai): This method should be abstract, having empty body here
195    // makes the merge to the Android easy.
196    public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
197        onShowCustomView(view, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, callback);
198    }
199
200    public abstract void onHideCustomView();
201
202    public abstract Bitmap getDefaultVideoPoster();
203
204    //--------------------------------------------------------------------------------------------
205    //                              Other WebView-specific methods
206    //--------------------------------------------------------------------------------------------
207    //
208    public abstract void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
209            boolean isDoneCounting);
210
211    /**
212     * Called whenever there is a new content picture available.
213     * @param picture New picture.
214     */
215    public abstract void onNewPicture(Picture picture);
216
217}
218