blob: 553a6059dd288c28e5d1f2e11d7b6d63c890966b [file] [log] [blame]
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.androidx.webkit;
import static androidx.webkit.WebViewAssetLoader.AssetsPathHandler;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.AbsoluteSizeSpan;
import android.view.View;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.webkit.JavaScriptReplyProxy;
import androidx.webkit.WebMessageCompat;
import androidx.webkit.WebMessagePortCompat;
import androidx.webkit.WebViewAssetLoader;
import androidx.webkit.WebViewCompat;
import androidx.webkit.WebViewFeature;
import java.util.Arrays;
import java.util.HashSet;
/**
* An {@link Activity} to exercise WebMessageListener related functionality.
*/
@SuppressLint("RestrictedApi")
public class WebMessageListenerActivity extends AppCompatActivity {
private TextView mTextView;
private final Uri mExampleUri = new Uri.Builder()
.scheme("https")
.authority("example.com")
.appendPath("androidx_webkit")
.appendPath("example")
.appendPath("assets")
.build();
private Button mReplyProxyButton;
private Button mPortButton;
private static class MyWebViewClient extends WebViewClient {
private final WebViewAssetLoader mAssetLoader;
MyWebViewClient(WebViewAssetLoader loader) {
mAssetLoader = loader;
}
@Override
@RequiresApi(21)
public WebResourceResponse shouldInterceptRequest(WebView view,
WebResourceRequest request) {
return mAssetLoader.shouldInterceptRequest(request.getUrl());
}
@Override
@SuppressWarnings("deprecation") // use the old one for compatibility with all API levels.
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
return mAssetLoader.shouldInterceptRequest(Uri.parse(url));
}
}
private static class ReplyMessageListener implements WebViewCompat.WebMessageListener {
private JavaScriptReplyProxy mReplyProxy;
ReplyMessageListener(Button button) {
button.setOnClickListener((View v) -> {
if (mReplyProxy == null) return;
mReplyProxy.postMessage("ReplyProxy button clicked.");
});
}
@Override
public void onPostMessage(WebView view, WebMessageCompat message, Uri sourceOrigin,
boolean isMainFrame, JavaScriptReplyProxy replyProxy) {
if (message.getData().equals("initialization")) {
mReplyProxy = replyProxy;
}
}
}
private static class MessagePortMessageListener implements WebViewCompat.WebMessageListener {
private WebMessagePortCompat mPort;
MessagePortMessageListener(Button button) {
button.setOnClickListener((View v) -> {
if (mPort == null) return;
mPort.postMessage(new WebMessageCompat("Port button clicked."));
});
}
@Override
public void onPostMessage(WebView view, WebMessageCompat message, Uri sourceOrigin,
boolean isMainFrame, JavaScriptReplyProxy replyProxy) {
if (message.getData().equals("send port")) {
mPort = message.getPorts()[0];
}
}
}
private static class ToastMessageListener implements WebViewCompat.WebMessageListener {
private final Context mContext;
ToastMessageListener(Context context) {
mContext = context;
}
@Override
public void onPostMessage(WebView view, WebMessageCompat message, Uri sourceOrigin,
boolean isMainFrame, JavaScriptReplyProxy replyProxy) {
Toast.makeText(mContext, "Toast: " + message.getData(), Toast.LENGTH_SHORT).show();
}
}
private static class MultipleMessagesListener implements WebViewCompat.WebMessageListener {
private final TextView mTextView;
private int mCounter = 0;
MultipleMessagesListener(TextView textView) {
mTextView = textView;
}
@Override
public void onPostMessage(WebView view, WebMessageCompat message, Uri sourceOrigin,
boolean isMainFrame, JavaScriptReplyProxy replyProxy) {
replyProxy.postMessage(message.getData());
mCounter++;
if (mCounter % 100 == 0) {
mTextView.setText(TextUtils.concat(
createNativeTitle(), "\n", "" + mCounter + " messages received."));
}
}
}
@SuppressLint("SetJavascriptEnabled")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_message_listener);
setTitle(R.string.web_message_listener_activity_title);
WebkitHelpers.appendWebViewVersionToTitle(this);
if (!WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) {
WebkitHelpers.showMessageInActivity(
WebMessageListenerActivity.this, R.string.webkit_api_not_available);
return;
}
// Use WebViewAssetLoader to load html page from app's assets.
WebViewAssetLoader assetLoader =
new WebViewAssetLoader.Builder()
.setDomain("example.com")
.addPathHandler(mExampleUri.getPath() + "/", new AssetsPathHandler(this))
.build();
mTextView = findViewById(R.id.textview);
mTextView.setText(createNativeTitle());
mReplyProxyButton = findViewById(R.id.button_reply_proxy);
mPortButton = findViewById(R.id.button_port);
WebView webView = findViewById(R.id.webview);
webView.setWebViewClient(new MyWebViewClient(assetLoader));
webView.getSettings().setJavaScriptEnabled(true);
HashSet<String> allowedOriginRules = new HashSet<>(Arrays.asList("https://example.com"));
// Add WebMessageListeners.
WebViewCompat.addWebMessageListener(webView, "replyObject", allowedOriginRules,
new ReplyMessageListener(mReplyProxyButton));
WebViewCompat.addWebMessageListener(webView, "replyWithMessagePortObject",
allowedOriginRules, new MessagePortMessageListener(mPortButton));
WebViewCompat.addWebMessageListener(
webView, "toastObject", allowedOriginRules, new ToastMessageListener(this));
WebViewCompat.addWebMessageListener(webView, "multipleMessagesObject", allowedOriginRules,
new MultipleMessagesListener(mTextView));
webView.loadUrl(
Uri.withAppendedPath(mExampleUri, "www/web_message_listener.html").toString());
}
private static CharSequence createNativeTitle() {
final String title = "Native View";
SpannableString ss = new SpannableString(title);
ss.setSpan(new AbsoluteSizeSpan(55, true), 0, title.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return ss;
}
}