blob: 043f66abefe9c7c945962fe7a56566b946695021 [file] [log] [blame]
// Copyright (c) 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/ui/webui/flags/flags_ui_handler.h"
#include "base/bind.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/common/channel_info.h"
#include "components/flags_ui/flags_storage.h"
#include "components/flags_ui/flags_ui_constants.h"
#include "components/version_info/channel.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/crosapi/browser_data_migrator.h"
#include "chrome/browser/ash/crosapi/browser_util.h"
#include "chrome/browser/ash/settings/about_flags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#endif
FlagsUIHandler::FlagsUIHandler()
: access_(flags_ui::kGeneralAccessFlagsOnly),
experimental_features_callback_id_(""),
deprecated_features_only_(false) {}
FlagsUIHandler::~FlagsUIHandler() {}
void FlagsUIHandler::RegisterMessages() {
web_ui()->RegisterDeprecatedMessageCallback(
flags_ui::kRequestExperimentalFeatures,
base::BindRepeating(&FlagsUIHandler::HandleRequestExperimentalFeatures,
base::Unretained(this)));
web_ui()->RegisterDeprecatedMessageCallback(
flags_ui::kEnableExperimentalFeature,
base::BindRepeating(
&FlagsUIHandler::HandleEnableExperimentalFeatureMessage,
base::Unretained(this)));
web_ui()->RegisterDeprecatedMessageCallback(
flags_ui::kSetOriginListFlag,
base::BindRepeating(&FlagsUIHandler::HandleSetOriginListFlagMessage,
base::Unretained(this)));
web_ui()->RegisterDeprecatedMessageCallback(
flags_ui::kRestartBrowser,
base::BindRepeating(&FlagsUIHandler::HandleRestartBrowser,
base::Unretained(this)));
web_ui()->RegisterDeprecatedMessageCallback(
flags_ui::kResetAllFlags,
base::BindRepeating(&FlagsUIHandler::HandleResetAllFlags,
base::Unretained(this)));
#if defined(OS_CHROMEOS)
web_ui()->RegisterDeprecatedMessageCallback(
flags_ui::kCrosUrlFlagsRedirect,
base::BindRepeating(&FlagsUIHandler::HandleCrosUrlFlagsRedirect,
base::Unretained(this)));
#endif
}
void FlagsUIHandler::Init(flags_ui::FlagsStorage* flags_storage,
flags_ui::FlagAccess access) {
flags_storage_.reset(flags_storage);
access_ = access;
if (!experimental_features_callback_id_.empty())
SendExperimentalFeatures();
}
void FlagsUIHandler::HandleRequestExperimentalFeatures(
const base::ListValue* args) {
AllowJavascript();
const base::Value& callback_id = args->GetList()[0];
experimental_features_callback_id_ = callback_id.GetString();
// Bail out if the handler hasn't been initialized yet. The request will be
// handled after the initialization.
if (!flags_storage_) {
return;
}
SendExperimentalFeatures();
}
void FlagsUIHandler::SendExperimentalFeatures() {
base::DictionaryValue results;
base::Value::ListStorage supported_features;
base::Value::ListStorage unsupported_features;
if (deprecated_features_only_) {
about_flags::GetFlagFeatureEntriesForDeprecatedPage(
flags_storage_.get(), access_, supported_features,
unsupported_features);
} else {
about_flags::GetFlagFeatureEntries(flags_storage_.get(), access_,
supported_features,
unsupported_features);
}
results.SetKey(flags_ui::kSupportedFeatures, base::Value(supported_features));
results.SetKey(flags_ui::kUnsupportedFeatures,
base::Value(unsupported_features));
results.SetBoolean(flags_ui::kNeedsRestart,
about_flags::IsRestartNeededToCommitChanges());
results.SetBoolean(flags_ui::kShowOwnerWarning,
access_ == flags_ui::kGeneralAccessFlagsOnly);
#if BUILDFLAG(IS_CHROMEOS_ASH)
const bool showSystemFlagsLink = crosapi::browser_util::IsLacrosEnabled();
#else
const bool showSystemFlagsLink = true;
#endif
results.SetBoolean(flags_ui::kShowSystemFlagsLink, showSystemFlagsLink);
#if defined(OS_WIN) || defined(OS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH)
version_info::Channel channel = chrome::GetChannel();
results.SetBoolean(
flags_ui::kShowBetaChannelPromotion,
channel == version_info::Channel::STABLE && !deprecated_features_only_);
results.SetBoolean(
flags_ui::kShowDevChannelPromotion,
channel == version_info::Channel::BETA && !deprecated_features_only_);
#else
results.SetBoolean(flags_ui::kShowBetaChannelPromotion, false);
results.SetBoolean(flags_ui::kShowDevChannelPromotion, false);
#endif
ResolveJavascriptCallback(base::Value(experimental_features_callback_id_),
results);
experimental_features_callback_id_.clear();
}
void FlagsUIHandler::HandleEnableExperimentalFeatureMessage(
const base::ListValue* args) {
DCHECK(flags_storage_);
DCHECK_EQ(2u, args->GetList().size());
if (args->GetList().size() != 2)
return;
if (!args->GetList()[0].is_string() || !args->GetList()[1].is_string()) {
NOTREACHED();
return;
}
const std::string& entry_internal_name = args->GetList()[0].GetString();
const std::string& enable_str = args->GetList()[1].GetString();
if (entry_internal_name.empty()) {
NOTREACHED();
return;
}
about_flags::SetFeatureEntryEnabled(flags_storage_.get(), entry_internal_name,
enable_str == "true");
}
void FlagsUIHandler::HandleSetOriginListFlagMessage(
const base::ListValue* args) {
DCHECK(flags_storage_);
if (args->GetList().size() != 2) {
NOTREACHED();
return;
}
if (!args->GetList()[0].is_string() || !args->GetList()[1].is_string()) {
NOTREACHED();
return;
}
const std::string& entry_internal_name = args->GetList()[0].GetString();
const std::string& value_str = args->GetList()[1].GetString();
if (entry_internal_name.empty()) {
NOTREACHED();
return;
}
about_flags::SetOriginListFlag(entry_internal_name, value_str,
flags_storage_.get());
}
void FlagsUIHandler::HandleRestartBrowser(const base::ListValue* args) {
DCHECK(flags_storage_);
#if BUILDFLAG(IS_CHROMEOS_ASH)
// On Chrome OS be less intrusive and restart inside the user session after
// we apply the newly selected flags.
VLOG(1) << "Restarting to apply per-session flags...";
ash::about_flags::FeatureFlagsUpdate(*flags_storage_,
Profile::FromWebUI(web_ui())->GetPrefs())
.UpdateSessionManager();
// Call `ClearMigrationStep()` so that we can run migration for the following
// case.
// 1. User has lacros enabled.
// 2. User logs in and migration is completed.
// 3. User disabled lacros in session.
// 4. User re-enables lacros in session.
ash::BrowserDataMigrator::ClearMigrationStep(
g_browser_process->local_state());
#endif
chrome::AttemptRestart();
}
void FlagsUIHandler::HandleResetAllFlags(const base::ListValue* args) {
DCHECK(flags_storage_);
about_flags::ResetAllFlags(flags_storage_.get());
}
#if defined(OS_CHROMEOS)
void FlagsUIHandler::HandleCrosUrlFlagsRedirect(const base::ListValue* args) {
about_flags::CrosUrlFlagsRedirect();
}
#endif