chromium/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewTracingActivity.java

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.webview_shell;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.SystemClock;
import android.webkit.WebSettings;
import android.webkit.WebView;

import androidx.webkit.TracingConfig;
import androidx.webkit.TracingController;
import androidx.webkit.WebViewClientCompat;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.Executors;

/**
 * This activity is designed for telemetry testing of WebView Tracing API.
 *
 * In particular it allows to measure time for loading a given URL with or without
 * tracing enabled. It also provides the overall tracing time, i.e. time it takes from
 * starting tracing until completion when all traces are written to disk.
 *
 * Example usage:
 * $ adb shell am start -n org.chromium.webview_shell/.WebViewTracingActivity -a VIEW -d \
 *   http://www.google.com --ez enableTracing true
 *
 */
public class WebViewTracingActivity extends Activity {
    private static final String TAG = "WebViewTracingActivity";

    private static long sUrlLoadTimeStartMs;
    private static long sUrlLoadTimeEndMs;

    private static long sOverallTracingTimeStartMs;
    private static long sOverallTracingTimeEndMs;

    private static class TracingLogger extends FileOutputStream {
        private long mByteCount;
        private Activity mActivity;

        public TracingLogger(String fileName, Activity activity) throws FileNotFoundException {
            super(fileName);
            mActivity = activity;
        }

        @Override
        public void write(byte[] chunk) throws IOException {
            mByteCount += chunk.length;
            super.write(chunk);
        }

        @Override
        public void close() throws IOException {
            super.close();
            sOverallTracingTimeEndMs = SystemClock.elapsedRealtime();
            android.util.Log.i(
                    TAG,
                    "TracingLogger.complete(), byte count = "
                            + getByteCount()
                            + ", overall duration (ms) = "
                            + (sOverallTracingTimeEndMs - sOverallTracingTimeStartMs));
            mActivity.finish();
        }

        public long getByteCount() {
            return mByteCount;
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setTitle("WebViewTracingActivity");

        Intent intent = getIntent();
        String url = getUrlFromIntent(intent);
        if (url == null) {
            url = "about:blank";
        }

        boolean enableTracing = false;
        if (intent.getExtras() != null) {
            enableTracing = intent.getExtras().getBoolean("enableTracing", false);
        }

        loadUrl(url, enableTracing);
    }

    private void loadUrl(final String url, boolean enableTracing) {
        final Activity activity = this;
        WebView webView = new WebView(this);
        setContentView(webView);
        WebSettings settings = webView.getSettings();
        settings.setJavaScriptEnabled(true);
        final TracingController tracingController = TracingController.getInstance();

        webView.setWebViewClient(
                new WebViewClientCompat() {
                    @Override
                    public void onPageFinished(WebView view, String url) {
                        super.onPageFinished(view, url);
                        sUrlLoadTimeEndMs = SystemClock.elapsedRealtime();
                        android.util.Log.i(
                                TAG,
                                "onPageFinished(), enableTracing = "
                                        + enableTracing
                                        + ", url = "
                                        + url
                                        + ", urlLoadTimeMillis = "
                                        + (sUrlLoadTimeEndMs - sUrlLoadTimeStartMs));

                        if (enableTracing) {
                            String outFileName = getFilesDir() + "/webview_tracing.json";
                            try {
                                tracingController.stop(
                                        new TracingLogger(outFileName, activity),
                                        Executors.newSingleThreadExecutor());
                            } catch (FileNotFoundException e) {
                                throw new RuntimeException(e);
                            }
                        } else {
                            activity.finish();
                        }
                    }
                });

        if (enableTracing) {
            sOverallTracingTimeStartMs = SystemClock.elapsedRealtime();
            tracingController.start(
                    new TracingConfig.Builder()
                            .addCategories(TracingConfig.CATEGORIES_WEB_DEVELOPER)
                            .setTracingMode(TracingConfig.RECORD_UNTIL_FULL)
                            .build());
        }
        sUrlLoadTimeStartMs = SystemClock.elapsedRealtime();
        webView.loadUrl(url);
    }

    private static String getUrlFromIntent(Intent intent) {
        return intent != null ? intent.getDataString() : null;
    }
}