chromium/android_webview/browser/supervised_user/aw_supervised_user_url_classifier.cc

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

#include "android_webview/browser/supervised_user/aw_supervised_user_url_classifier.h"

#include "android_webview/browser/aw_browser_process.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/metrics/histogram_functions.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"
#include "url/android/gurl_android.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "android_webview/browser_jni_headers/AwSupervisedUserUrlClassifier_jni.h"

using base::android::AttachCurrentThread;

namespace android_webview {

AwSupervisedUserUrlClassifier::AwSupervisedUserUrlClassifier() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  local_state_ = AwBrowserProcess::GetInstance()->local_state();
  JNIEnv* env = AttachCurrentThread();
  platform_supports_url_checks_ =
      Java_AwSupervisedUserUrlClassifier_shouldCreateThrottle(env);
}

// static
AwSupervisedUserUrlClassifier* AwSupervisedUserUrlClassifier::GetInstance() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  static base::NoDestructor<AwSupervisedUserUrlClassifier> instance;
  return instance.get();
}

// static
void AwSupervisedUserUrlClassifier::RegisterPrefs(
    PrefRegistrySimple* registry) {
  registry->RegisterBooleanPref(prefs::kShouldBlockRestrictedContent, false);
}

bool AwSupervisedUserUrlClassifier::ShouldCreateThrottle() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  bool user_requires_url_checks =
      local_state_->GetBoolean(prefs::kShouldBlockRestrictedContent);
  return platform_supports_url_checks_ && user_requires_url_checks;
}

void AwSupervisedUserUrlClassifier::ShouldBlockUrl(
    const GURL& request_url,
    UrlClassifierCallback callback) {
  JNIEnv* env = AttachCurrentThread();
  auto request_url_java = url::GURLAndroid::FromNativeGURL(env, request_url);
  intptr_t callback_id = reinterpret_cast<intptr_t>(
      new UrlClassifierCallback(std::move(callback)));

  return Java_AwSupervisedUserUrlClassifier_shouldBlockUrl(
      env, request_url_java, callback_id);
}

void AwSupervisedUserUrlClassifier::SetUserRequiresUrlChecks(
    bool user_requires_url_checks) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  bool old_value =
      local_state_->GetBoolean(prefs::kShouldBlockRestrictedContent);
  local_state_->SetBoolean(prefs::kShouldBlockRestrictedContent,
                           user_requires_url_checks);
  bool value_matches = old_value == user_requires_url_checks;
  base::UmaHistogramBoolean(
      "Android.WebView.RestrictedContentBlocking.ApiCallMatchesDiskCache",
      value_matches);
}

static void JNI_AwSupervisedUserUrlClassifier_OnShouldBlockUrlResult(
    JNIEnv* env,
    jlong callback_id,
    jboolean shouldBlockUrl) {
  std::unique_ptr<UrlClassifierCallback> cb(
      reinterpret_cast<UrlClassifierCallback*>(callback_id));
  std::move(*cb).Run(shouldBlockUrl);
}

static void JNI_AwSupervisedUserUrlClassifier_SetUserRequiresUrlChecks(
    JNIEnv* env,
    jboolean user_requires_url_checks) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  AwSupervisedUserUrlClassifier::GetInstance()->SetUserRequiresUrlChecks(
      user_requires_url_checks);
}

}  // namespace android_webview