blob: d7171b0db45328fcdd9e76d84305911ac0695847 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/dev_ui/dev_ui_module_provider.h"
#include <memory>
#include <utility>
#include "base/logging.h"
#include "base/task/post_task.h"
#include "chrome/android/modules/dev_ui/provider/jni_headers/DevUiModuleProvider_jni.h"
#include "chrome/browser/android/dfm_resource_bundle_helper.h"
namespace dev_ui {
namespace {
constexpr base::TaskTraits kWorkerTaskTraits = {
base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN};
} // namespace
// static
DevUiModuleProvider& DevUiModuleProvider::GetInstance() {
static base::NoDestructor<DevUiModuleProvider> instance;
return *instance;
}
bool DevUiModuleProvider::ModuleInstalled() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return Java_DevUiModuleProvider_isModuleInstalled(
base::android::AttachCurrentThread());
}
bool DevUiModuleProvider::ModuleLoaded() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return DevUiModuleProvider::GetInstance().is_loaded_;
}
void DevUiModuleProvider::InstallModule(
base::OnceCallback<void(bool)> on_finished) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Also use the call's side effect of ensuring that split compat is loaded.
// TODO(tiborg): Once ModuleInstalled() is made more light-weight, add
// explicit split compat loading code here.
if (ModuleInstalled()) {
std::move(on_finished).Run(true);
return;
}
on_attempted_install_callbacks_.push(std::move(on_finished));
// Don't request DevUI module multiple times in parallel.
if (on_attempted_install_callbacks_.size() > 1)
return;
// This should always return, since there is no InfoBar UI to retry (thus
// avoiding crbug.com/996925 and crbug.com/996959).
Java_DevUiModuleProvider_installModule(base::android::AttachCurrentThread(),
j_dev_ui_module_provider_);
}
// Called by Java.
void DevUiModuleProvider::OnInstallResult(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
bool success) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_GT(on_attempted_install_callbacks_.size(), 0UL);
while (!on_attempted_install_callbacks_.empty()) {
std::move(on_attempted_install_callbacks_.front()).Run(success);
on_attempted_install_callbacks_.pop();
}
}
void DevUiModuleProvider::LoadModule(base::OnceCallback<void()> on_loaded) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (ModuleLoaded()) {
std::move(on_loaded).Run();
return;
}
on_loaded_callbacks_.push(std::move(on_loaded));
// Don't load multiple times in parallel.
if (on_loaded_callbacks_.size() > 1)
return;
// android::LoadDevUiResources() is assumed to always succeed.
base::PostTaskAndReply(FROM_HERE, kWorkerTaskTraits,
base::BindOnce(&android::LoadDevUiResources),
base::BindOnce(&DevUiModuleProvider::OnLoadedModule,
base::Unretained(this)));
}
DevUiModuleProvider::DevUiModuleProvider()
: j_dev_ui_module_provider_(Java_DevUiModuleProvider_Constructor(
base::android::AttachCurrentThread(),
reinterpret_cast<jlong>(this))) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
DevUiModuleProvider::~DevUiModuleProvider() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Java_DevUiModuleProvider_onNativeDestroy(base::android::AttachCurrentThread(),
j_dev_ui_module_provider_);
}
void DevUiModuleProvider::OnLoadedModule() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
is_loaded_ = true;
DCHECK_GT(on_loaded_callbacks_.size(), 0UL);
while (!on_loaded_callbacks_.empty()) {
std::move(on_loaded_callbacks_.front()).Run();
on_loaded_callbacks_.pop();
}
}
} // namespace dev_ui