blob: e75c7d953bf95d6271835ae08f22b0738acb9e92 [file] [log] [blame]
// Copyright (c) 2012 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_ui.h"
#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/flags_ui_handler.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "components/flags_ui/flags_ui_constants.h"
#include "components/flags_ui/flags_ui_pref_names.h"
#include "components/flags_ui/pref_service_flags_storage.h"
#include "components/grit/components_resources.h"
#include "components/grit/components_scaled_resources.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/strings/grit/components_chromium_strings.h"
#include "components/strings/grit/components_strings.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/browser/web_ui_message_handler.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#if defined(OS_CHROMEOS)
#include "base/system/sys_info.h"
#include "chrome/browser/chromeos/login/session/user_session_manager.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/owner_flags_storage.h"
#include "components/account_id/account_id.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/user_manager/user_manager.h"
#endif
using content::WebContents;
using content::WebUIMessageHandler;
namespace {
content::WebUIDataSource* CreateFlagsUIHTMLSource() {
content::WebUIDataSource* source =
content::WebUIDataSource::Create(chrome::kChromeUIFlagsHost);
source->OverrideContentSecurityPolicyScriptSrc(
"script-src chrome://resources 'self' 'unsafe-eval';");
source->AddString(flags_ui::kVersion, version_info::GetVersionNumber());
#if defined(OS_CHROMEOS)
if (!user_manager::UserManager::Get()->IsCurrentUserOwner() &&
base::SysInfo::IsRunningOnChromeOS()) {
// Set the string to show which user can actually change the flags.
std::string owner;
chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
source->AddString("owner-warning",
l10n_util::GetStringFUTF16(IDS_FLAGS_UI_OWNER_WARNING,
base::UTF8ToUTF16(owner)));
} else {
source->AddString("owner-warning", base::string16());
}
#endif
source->AddResourcePath(flags_ui::kFlagsJS, IDR_FLAGS_UI_FLAGS_JS);
source->AddResourcePath(flags_ui::kFlagsStyleLoaderJS,
IDR_FLAGS_UI_FLAGS_STYLE_LOADER_JS);
source->AddResourcePath(flags_ui::kEnterpriseFlagsCSS,
IDR_FLAGS_UI_FLAGS_ENTERPRISE_CSS);
source->AddResourcePath(flags_ui::kFlagsCSS, IDR_FLAGS_UI_FLAGS_CSS);
source->SetDefaultResource(IDR_FLAGS_UI_FLAGS_HTML);
return source;
}
#if defined(OS_CHROMEOS)
// On ChromeOS verifying if the owner is signed in is async operation and only
// after finishing it the UI can be properly populated. This function is the
// callback for whether the owner is signed in. It will respectively pick the
// proper PrefService for the flags interface.
template <class T>
void FinishInitialization(base::WeakPtr<T> flags_ui,
Profile* profile,
FlagsUIHandler* dom_handler,
bool current_user_is_owner) {
DCHECK(!profile->IsOffTheRecord());
// If the flags_ui has gone away, there's nothing to do.
if (!flags_ui)
return;
// On Chrome OS the owner can set system wide flags and other users can only
// set flags for their own session.
// Note that |dom_handler| is owned by the web ui that owns |flags_ui|, so
// it is still alive if |flags_ui| is.
if (current_user_is_owner) {
chromeos::OwnerSettingsServiceChromeOS* service =
chromeos::OwnerSettingsServiceChromeOSFactory::GetForBrowserContext(
profile);
dom_handler->Init(new chromeos::about_flags::OwnerFlagsStorage(
profile->GetPrefs(), service),
flags_ui::kOwnerAccessToFlags);
} else {
dom_handler->Init(
new flags_ui::PrefServiceFlagsStorage(profile->GetPrefs()),
flags_ui::kGeneralAccessFlagsOnly);
}
}
#endif
} // namespace
// static
void FlagsUI::AddFlagsStrings(content::WebUIDataSource* source) {
// Strings added here are all marked a non-translatable, so they are not
// actually localized.
source->AddLocalizedString(flags_ui::kFlagsRestartNotice,
IDS_FLAGS_UI_RELAUNCH_NOTICE);
source->AddLocalizedString("available", IDS_FLAGS_UI_AVAILABLE_FEATURE);
source->AddLocalizedString("clear-search", IDS_FLAGS_UI_CLEAR_SEARCH);
source->AddLocalizedString("disabled", IDS_FLAGS_UI_DISABLED_FEATURE);
source->AddLocalizedString("enabled", IDS_FLAGS_UI_ENABLED_FEATURE);
source->AddLocalizedString("experiment-enabled",
IDS_FLAGS_UI_EXPERIMENT_ENABLED);
source->AddLocalizedString("no-results", IDS_FLAGS_UI_NO_RESULTS);
source->AddLocalizedString("not-available-platform",
IDS_FLAGS_UI_NOT_AVAILABLE_ON_PLATFORM);
source->AddLocalizedString("page-warning", IDS_FLAGS_UI_PAGE_WARNING);
source->AddLocalizedString("page-warning-explanation",
IDS_FLAGS_UI_PAGE_WARNING_EXPLANATION);
source->AddLocalizedString("relaunch", IDS_FLAGS_UI_RELAUNCH);
source->AddLocalizedString("reset", IDS_FLAGS_UI_PAGE_RESET);
source->AddLocalizedString("reset-complete", IDS_FLAGS_UI_RESET_COMPLETE);
source->AddLocalizedString("search-placeholder",
IDS_FLAGS_UI_SEARCH_PLACEHOLDER);
source->AddLocalizedString("title", IDS_FLAGS_UI_TITLE);
source->AddLocalizedString("unavailable", IDS_FLAGS_UI_UNAVAILABLE_FEATURE);
}
// static
void FlagsEnterpriseUI::AddEnterpriseStrings(content::WebUIDataSource* source) {
source->AddLocalizedString(flags_ui::kFlagsRestartNotice,
IDS_ENTERPRISE_SETTINGS_RELAUNCH_NOTICE);
source->AddLocalizedString("available",
IDS_ENTERPRISE_SETTINGS_AVAILABLE_FEATURE);
source->AddLocalizedString("clear-search", IDS_ENTERPRISE_UI_CLEAR_SEARCH);
source->AddLocalizedString("disabled",
IDS_ENTERPRISE_SETTINGS_DISABLED_FEATURE);
source->AddLocalizedString("enabled",
IDS_ENTERPRISE_SETTINGS_ENABLED_FEATURE);
source->AddLocalizedString("experiment-enabled",
IDS_ENTERPRISE_UI_EXPERIMENT_ENABLED);
source->AddLocalizedString("no-results", IDS_ENTERPRISE_SETTINGS_NO_RESULTS);
source->AddLocalizedString("not-available-platform",
IDS_ENTERPRISE_SETTINGS_NOT_AVAILABLE_ON_PLATFORM);
source->AddLocalizedString("page-warning",
IDS_ENTERPRISE_SETTINGS_PAGE_WARNING);
source->AddLocalizedString("page-warning-explanation",
IDS_ENTERPRISE_SETTINGS_PAGE_WARNING_EXPLANATION);
source->AddLocalizedString("relaunch", IDS_ENTERPRISE_SETTINGS_RELAUNCH);
source->AddLocalizedString("reset", IDS_ENTERPRISE_SETTINGS_PAGE_RESET);
source->AddLocalizedString("reset-complete",
IDS_ENTERPRISE_UI_RESET_COMPLETE);
source->AddLocalizedString("search-placeholder",
IDS_ENTERPRISE_SETTINGS_SEARCH_PLACEHOLDER);
source->AddLocalizedString("title", IDS_ENTERPRISE_SETTINGS_TITLE);
source->AddLocalizedString("unavailable",
IDS_ENTERPRISE_SETTINGS_UNAVAILABLE_FEATURE);
}
template <class T>
FlagsUIHandler* InitializeHandler(content::WebUI* web_ui,
Profile* profile,
base::WeakPtrFactory<T>& weak_factory) {
auto handler_owner = std::make_unique<FlagsUIHandler>();
FlagsUIHandler* handler = handler_owner.get();
web_ui->AddMessageHandler(std::move(handler_owner));
#if defined(OS_CHROMEOS)
// Bypass possible incognito profile.
Profile* original_profile = profile->GetOriginalProfile();
if (base::SysInfo::IsRunningOnChromeOS() &&
chromeos::OwnerSettingsServiceChromeOSFactory::GetForBrowserContext(
original_profile)) {
chromeos::OwnerSettingsServiceChromeOS* service =
chromeos::OwnerSettingsServiceChromeOSFactory::GetForBrowserContext(
original_profile);
service->IsOwnerAsync(base::Bind(&FinishInitialization<T>,
weak_factory.GetWeakPtr(),
original_profile, handler));
} else {
FinishInitialization(weak_factory.GetWeakPtr(), original_profile, handler,
false /* current_user_is_owner */);
}
#else
handler->Init(
new flags_ui::PrefServiceFlagsStorage(g_browser_process->local_state()),
flags_ui::kOwnerAccessToFlags);
#endif
return handler;
}
FlagsUI::FlagsUI(content::WebUI* web_ui)
: WebUIController(web_ui), weak_factory_(this) {
Profile* profile = Profile::FromWebUI(web_ui);
auto* handler = InitializeHandler(web_ui, profile, weak_factory_);
DCHECK(handler);
handler->set_enterprise_features_only(false);
// Set up the about:flags source.
auto* source = CreateFlagsUIHTMLSource();
AddFlagsStrings(source);
content::WebUIDataSource::Add(profile, source);
}
FlagsUI::~FlagsUI() {
}
// static
base::RefCountedMemory* FlagsUI::GetFaviconResourceBytes(
ui::ScaleFactor scale_factor) {
return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
IDR_FLAGS_FAVICON, scale_factor);
}
FlagsEnterpriseUI::FlagsEnterpriseUI(content::WebUI* web_ui)
: WebUIController(web_ui) {
Profile* profile = Profile::FromWebUI(web_ui);
auto* handler = InitializeHandler(web_ui, profile, weak_factory_);
DCHECK(handler);
handler->set_enterprise_features_only(true);
// Set up the about:enterprise-flags source.
auto* source = CreateFlagsUIHTMLSource();
AddEnterpriseStrings(source);
content::WebUIDataSource::Add(profile, source);
}
FlagsEnterpriseUI::~FlagsEnterpriseUI() {}
// static
bool FlagsEnterpriseUI::IsEnterpriseUrl(const GURL& url) {
return url.path() == "/enterprise" || url.path() == "/enterprise/";
}