chromium/android_webview/browser/aw_browser_process.cc

// Copyright 2019 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/aw_browser_process.h"

#include "android_webview/browser/aw_browser_context.h"
#include "android_webview/browser/aw_enterprise_authentication_app_link_manager.h"
#include "android_webview/browser/component_updater/registration.h"
#include "android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h"
#include "android_webview/browser/metrics/visibility_metrics_logger.h"
#include "android_webview/common/crash_reporter/crash_keys.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/base_paths_posix.h"
#include "base/path_service.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "components/component_updater/android/component_loader_policy.h"
#include "components/crash/core/common/crash_key.h"
#include "components/embedder_support/origin_trials/origin_trials_settings_storage.h"
#include "components/os_crypt/async/browser/os_crypt_async.h"
#include "components/safe_browsing/core/common/features.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/process_visibility_util.h"

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

using content::BrowserThread;

namespace android_webview {

namespace prefs {

// String that specifies the Android account type to use for Negotiate
// authentication.
const char kAuthAndroidNegotiateAccountType[] =
    "auth.android_negotiate_account_type";

// Allowlist containing servers for which Integrated Authentication is enabled.
// This pref should match |prefs::kAuthServerAllowlist|.
const char kAuthServerAllowlist[] = "auth.server_allowlist";

// This pref contains a list of authentication urls, for which when webview is
// navigated to any of these urls, browse intent will be sent.
const char kEnterpriseAuthAppLinkPolicy[] = "enterprise_auth_app_link_policy";

}  // namespace prefs

namespace {
AwBrowserProcess* g_aw_browser_process = nullptr;
}  // namespace

// static
AwBrowserProcess* AwBrowserProcess::GetInstance() {
  return g_aw_browser_process;
}

AwBrowserProcess::AwBrowserProcess(
    AwFeatureListCreator* aw_feature_list_creator) {
  g_aw_browser_process = this;
  aw_feature_list_creator_ = aw_feature_list_creator;
  aw_contents_lifecycle_notifier_ =
      std::make_unique<AwContentsLifecycleNotifier>(base::BindRepeating(
          &AwBrowserProcess::OnLoseForeground, base::Unretained(this)));

  app_link_manager_ =
      std::make_unique<EnterpriseAuthenticationAppLinkManager>(local_state());

  origin_trials_settings_storage_ =
      std::make_unique<embedder_support::OriginTrialsSettingsStorage>();

  // Initialize OSCryptAsync with no providers. This delegates all encryption
  // operations to OSCrypt.
  os_crypt_async_ = std::make_unique<os_crypt_async::OSCryptAsync>(
      std::vector<
          std::pair<size_t, std::unique_ptr<os_crypt_async::KeyProvider>>>());
}

AwBrowserProcess::~AwBrowserProcess() {
  g_aw_browser_process = nullptr;
}

void AwBrowserProcess::PreMainMessageLoopRun() {
  pref_change_registrar_.Init(local_state());
  auto auth_pref_callback = base::BindRepeating(
      &AwBrowserProcess::OnAuthPrefsChanged, base::Unretained(this));
  pref_change_registrar_.Add(prefs::kAuthServerAllowlist, auth_pref_callback);
  pref_change_registrar_.Add(prefs::kAuthAndroidNegotiateAccountType,
                             auth_pref_callback);

  // Trigger async initialization of OSCrypt key providers.
  std::ignore = os_crypt_async_->GetInstance(base::DoNothing());

  InitSafeBrowsing();
}

PrefService* AwBrowserProcess::local_state() {
  if (!local_state_)
    CreateLocalState();
  return local_state_.get();
}

void AwBrowserProcess::CreateLocalState() {
  DCHECK(!local_state_);

  local_state_ = aw_feature_list_creator_->TakePrefService();
  DCHECK(local_state_);
}

void AwBrowserProcess::OnLoseForeground() {
  if (local_state_)
    local_state_->CommitPendingWrite();
}

AwBrowserPolicyConnector* AwBrowserProcess::browser_policy_connector() {
  if (!browser_policy_connector_)
    CreateBrowserPolicyConnector();
  return browser_policy_connector_.get();
}

VisibilityMetricsLogger* AwBrowserProcess::visibility_metrics_logger() {
  if (!visibility_metrics_logger_) {
    visibility_metrics_logger_ = std::make_unique<VisibilityMetricsLogger>();

    visibility_metrics_logger_->SetOnVisibilityChangedCallback(
        base::BindRepeating([](bool visible) {
          content::OnBrowserVisibilityChanged(visible);
        }));
  }
  return visibility_metrics_logger_.get();
}

void AwBrowserProcess::CreateBrowserPolicyConnector() {
  DCHECK(!browser_policy_connector_);

  browser_policy_connector_ =
      aw_feature_list_creator_->TakeBrowserPolicyConnector();
  DCHECK(browser_policy_connector_);
}

void AwBrowserProcess::InitSafeBrowsing() {
  CreateSafeBrowsingUIManager();
  CreateSafeBrowsingAllowlistManager();
}

void AwBrowserProcess::CreateSafeBrowsingUIManager() {
  safe_browsing_ui_manager_ = new AwSafeBrowsingUIManager();
}

void AwBrowserProcess::CreateSafeBrowsingAllowlistManager() {
  scoped_refptr<base::SequencedTaskRunner> background_task_runner =
      base::ThreadPool::CreateSequencedTaskRunner(
          {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
      content::GetIOThreadTaskRunner({});
  safe_browsing_allowlist_manager_ =
      std::make_unique<AwSafeBrowsingAllowlistManager>(background_task_runner,
                                                       io_task_runner);
}

safe_browsing::RemoteSafeBrowsingDatabaseManager*
AwBrowserProcess::GetSafeBrowsingDBManager() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  if (!safe_browsing_db_manager_) {
    safe_browsing_db_manager_ =
        new safe_browsing::RemoteSafeBrowsingDatabaseManager();
  }

  if (!safe_browsing_db_manager_started_) {
    // V4ProtocolConfig is not used. Just create one with empty values..
    safe_browsing::V4ProtocolConfig config("", false, "", "");
    safe_browsing_db_manager_->StartOnUIThread(
        GetSafeBrowsingUIManager()->GetURLLoaderFactory(), config);
    safe_browsing_db_manager_started_ = true;
  }

  return safe_browsing_db_manager_.get();
}

safe_browsing::TriggerManager*
AwBrowserProcess::GetSafeBrowsingTriggerManager() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (!safe_browsing_trigger_manager_) {
    safe_browsing_trigger_manager_ =
        std::make_unique<safe_browsing::TriggerManager>(
            GetSafeBrowsingUIManager(),
            /*local_state_prefs=*/nullptr);
  }

  return safe_browsing_trigger_manager_.get();
}

AwSafeBrowsingAllowlistManager*
AwBrowserProcess::GetSafeBrowsingAllowlistManager() const {
  return safe_browsing_allowlist_manager_.get();
}

AwSafeBrowsingUIManager* AwBrowserProcess::GetSafeBrowsingUIManager() const {
  return safe_browsing_ui_manager_.get();
}

os_crypt_async::OSCryptAsync* AwBrowserProcess::GetOSCryptAsync() const {
  return os_crypt_async_.get();
}

// static
void AwBrowserProcess::RegisterNetworkContextLocalStatePrefs(
    PrefRegistrySimple* pref_registry) {
  pref_registry->RegisterStringPref(prefs::kAuthServerAllowlist, std::string());
  pref_registry->RegisterStringPref(prefs::kAuthAndroidNegotiateAccountType,
                                    std::string());
}

void AwBrowserProcess::RegisterEnterpriseAuthenticationAppLinkPolicyPref(
    PrefRegistrySimple* pref_registry) {
  pref_registry->RegisterListPref(prefs::kEnterpriseAuthAppLinkPolicy);
}

network::mojom::HttpAuthDynamicParamsPtr
AwBrowserProcess::CreateHttpAuthDynamicParams() {
  network::mojom::HttpAuthDynamicParamsPtr auth_dynamic_params =
      network::mojom::HttpAuthDynamicParams::New();

  auth_dynamic_params->allowed_schemes = AwBrowserContext::GetAuthSchemes();
  auth_dynamic_params->server_allowlist =
      local_state()->GetString(prefs::kAuthServerAllowlist);
  auth_dynamic_params->android_negotiate_account_type =
      local_state()->GetString(prefs::kAuthAndroidNegotiateAccountType);

  auth_dynamic_params->ntlm_v2_enabled = true;

  return auth_dynamic_params;
}

void AwBrowserProcess::OnAuthPrefsChanged() {
  content::GetNetworkService()->ConfigureHttpAuthPrefs(
      CreateHttpAuthDynamicParams());
}

EnterpriseAuthenticationAppLinkManager*
AwBrowserProcess::GetEnterpriseAuthenticationAppLinkManager() {
  return app_link_manager_.get();
}

embedder_support::OriginTrialsSettingsStorage*
AwBrowserProcess::GetOriginTrialsSettingsStorage() {
  return origin_trials_settings_storage_.get();
}

// static
void AwBrowserProcess::TriggerMinidumpUploading() {
  Java_AwBrowserProcess_triggerMinidumpUploading(
      base::android::AttachCurrentThread());
}

// static
ApkType AwBrowserProcess::GetApkType() {
  return static_cast<ApkType>(
      Java_AwBrowserProcess_getApkType(base::android::AttachCurrentThread()));
}

static void JNI_AwBrowserProcess_SetProcessNameCrashKey(
    JNIEnv* env,
    const base::android::JavaParamRef<jstring>& processName) {
  static ::crash_reporter::CrashKeyString<64> crash_key(
      crash_keys::kAppProcessName);
  crash_key.Set(base::android::ConvertJavaStringToUTF8(env, processName));
}

static base::android::ScopedJavaLocalRef<jobjectArray>
JNI_AwBrowserProcess_GetComponentLoaderPolicies(JNIEnv* env) {
  return component_updater::AndroidComponentLoaderPolicy::
      ToJavaArrayOfAndroidComponentLoaderPolicy(env,
                                                GetComponentLoaderPolicies());
}

}  // namespace android_webview