blob: 8c66216ebe18a19013663389f8645db2c9b19724 [file] [log] [blame]
/*
* Copyright 2022 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 android.annotation.SuppressLint;
import android.app.Activity;
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.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.webkit.WebMessageCompat;
import androidx.webkit.WebMessagePortCompat;
import androidx.webkit.WebViewCompat;
import androidx.webkit.WebViewFeature;
import com.google.common.base.Charsets;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* An {@link Activity} to exercise WebMessageCompat related functionality.
*/
public class WebMessageCompatActivity extends AppCompatActivity {
private static final String TYPE_STRING = "String";
private static final String TYPE_ARRAY_BUFFER = "ArrayBuffer";
private static final String[] MESSAGE_TYPES = {TYPE_STRING, TYPE_ARRAY_BUFFER};
private static final boolean ARRAY_BUFFER_FEATURE_ENABLED =
WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_ARRAY_BUFFER);
private WebView mWebView;
private TextView mTextView, mPerfTextView;
private CheckBox mCheckBox;
private WebMessagePortCompat mPort;
private Spinner mSpinner;
private int mMessageCount = 0;
private int mExpectedCount = 0;
private long mTimeStamp;
static CharSequence createNativeTitle() {
final String title = "Native View\n";
SpannableString ss = new SpannableString(title);
ss.setSpan(new AbsoluteSizeSpan(55, true), 0, title.length() - 1,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return ss;
}
@SuppressLint("SetJavascriptEnabled")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_message_compat);
setTitle(R.string.web_message_compat_activity_title);
WebkitHelpers.appendWebViewVersionToTitle(this);
if (!WebViewFeature.isFeatureSupported(WebViewFeature.POST_WEB_MESSAGE)) {
WebkitHelpers.showMessageInActivity(WebMessageCompatActivity.this,
R.string.webkit_api_not_available);
return;
}
mWebView = findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new MyWebViewClient());
mTextView = findViewById(R.id.textview);
mPerfTextView = findViewById(R.id.textview_perf);
mCheckBox = findViewById(R.id.checkbox_window_message);
mSpinner = findViewById(R.id.message_type_spinner);
final ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_dropdown_item, MESSAGE_TYPES);
mSpinner.setAdapter(adapter);
// If GET_PAYLOAD feature is not supported, disable the type selection spinner.
mSpinner.setEnabled(ARRAY_BUFFER_FEATURE_ENABLED);
try (InputStream is = getAssets().open("www/web_message_compat.html")) {
String webContent = new String(ByteStreams.toByteArray(is), Charsets.UTF_8);
mWebView.loadDataWithBaseURL("https://example.com", webContent, "text/html", null,
null);
} catch (IOException e) {
throw new RuntimeException(e);
}
findViewById(R.id.button_send).setOnClickListener(view -> {
mExpectedCount = mMessageCount + 5000;
mTimeStamp = System.currentTimeMillis();
mSpinner.setEnabled(false);
sendMessage();
});
}
private void sendMessage() {
if (mMessageCount >= mExpectedCount) {
return;
}
final String selectedType = (String) mSpinner.getSelectedItem();
final WebMessageCompat message;
switch (selectedType) {
case TYPE_STRING:
message = new WebMessageCompat(String.valueOf(mMessageCount + 1));
break;
case TYPE_ARRAY_BUFFER:
byte[] bytes =
ByteBuffer.allocate(Integer.BYTES).putInt(mMessageCount + 1).array();
message = new WebMessageCompat(bytes);
break;
default:
// Should never happen.
throw new RuntimeException("Invalid type.");
}
if (mCheckBox.isChecked()) {
WebViewCompat.postWebMessage(mWebView, message, Uri.EMPTY);
} else {
mPort.postMessage(message);
}
}
private void refreshNativeText() {
mTextView.setText(TextUtils.concat(createNativeTitle(), String.valueOf(mMessageCount),
" messages received"));
}
private void refreshPerfText() {
mPerfTextView.setText("Average time over 5000 messages: "
+ (System.currentTimeMillis() - mTimeStamp) / 5000.0 + " ms");
}
private void setupMessagePort() {
WebMessagePortCompat[] ports = WebViewCompat.createWebMessageChannel(mWebView);
WebViewCompat.postWebMessage(mWebView,
new WebMessageCompat("setup", new WebMessagePortCompat[]{ports[0]}), Uri.EMPTY);
mPort = ports[1];
mPort.setWebMessageCallback(new WebMessagePortCompat.WebMessageCallbackCompat() {
@Override
public void onMessage(@NonNull WebMessagePortCompat port,
@Nullable WebMessageCompat message) {
switch (message.getType()) {
case WebMessageCompat.TYPE_STRING:
mMessageCount = Integer.parseInt(message.getData());
break;
case WebMessageCompat.TYPE_ARRAY_BUFFER:
mMessageCount = ByteBuffer.wrap(message.getArrayBuffer()).getInt();
break;
default:
// Should never happen
throw new RuntimeException("Invalid type: " + message.getType());
}
if (mMessageCount % 100 == 0) {
refreshNativeText();
}
if (mMessageCount == mExpectedCount) {
refreshPerfText();
mSpinner.setEnabled(ARRAY_BUFFER_FEATURE_ENABLED);
}
sendMessage();
}
});
}
private class MyWebViewClient extends WebViewClient {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
setupMessagePort();
view.setWebViewClient(null);
}
}
}