Introduce security curtain screen, compliant with UX requirements
This replaces placeholder UI that was previously added (but never released to any customers). UX requirement: http://shortn/_tWLEP1bbdp Implementation: Light mode: https://screenshot.googleplex.com/7UwiiWHr3HEVNzU.png Dark mode: https://screenshot.googleplex.com/BFWm4YsNSpwmkvN.png Note that the implementation is not 100% according to the UX requirements because to fully comply I have to wait until the OOBE code is migrated to their new look-and-feel, which is only scheduled for M116. I opened b/271099991 to ensure we do not forget to update the UX at that time. Low-Coverage-Reason: Will add browser pixel tests to ensure the curtain looks correct, but support for that is not there yet. Bug: b/266550061 Change-Id: I1a30de86140b7d796a55399e7573b8260d8560bc Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4254387 Reviewed-by: Demetrios Papadopoulos <dpapad@chromium.org> Reviewed-by: Renato Silva <rrsilva@google.com> Commit-Queue: Jeroen Dhollander <jeroendh@google.com> Cr-Commit-Position: refs/heads/main@{#1120420}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
2f32cad07c
commit
b93b120dca
ash
chrome
app
chromeos_strings.grdp
chromeos_strings_grdp
browser
resources
chromeos
remote_maintenance_curtain
ui
common
tools/gritsettings
@ -6443,14 +6443,6 @@ New install
|
||||
Please unlock to view notifications
|
||||
</message>
|
||||
|
||||
<!-- security curtain -->
|
||||
<message name="IDS_ASH_CURTAIN_TITLE" desc="Title text displayed to inform the user a remote admin has taken control of the ChromeOs device.">
|
||||
Your administrator is controlling your device
|
||||
</message>
|
||||
<message name="IDS_ASH_CURTAIN_DESCRIPTION" desc="Detailed description displayed to inform the user a remote admin has taken control of the ChromeOs device.">
|
||||
Your administrator has logged in to look into an issue. You can continue to use the device after the administrator gives the control back to you.
|
||||
</message>
|
||||
|
||||
<!-- pagination view -->
|
||||
<message name="IDS_ASH_PAGINATION_LEFT_ARROW_TOOLTIP" desc="The tooltip text used for pagination left arrow button." >
|
||||
Previous page
|
||||
|
@ -1 +0,0 @@
|
||||
1a2410a9c35ae9f30af8833c20f46f7490f09839
|
@ -1 +0,0 @@
|
||||
1a2410a9c35ae9f30af8833c20f46f7490f09839
|
@ -6,195 +6,75 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "ash/public/cpp/shelf_config.h"
|
||||
#include "ash/public/cpp/style/color_provider.h"
|
||||
#include "ash/resources/vector_icons/vector_icons.h"
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ash/assistant/ui/base/stack_layout.h"
|
||||
#include "ash/public/cpp/ash_web_view.h"
|
||||
#include "ash/public/cpp/ash_web_view_factory.h"
|
||||
#include "ash/wallpaper/wallpaper_constants.h"
|
||||
#include "ash/wallpaper/wallpaper_view.h"
|
||||
#include "base/check_deref.h"
|
||||
#include "chromeos/ui/vector_icons/vector_icons.h"
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/base/metadata/metadata_impl_macros.h"
|
||||
#include "ui/gfx/geometry/insets.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
#include "ui/gfx/image/image_skia.h"
|
||||
#include "ui/gfx/paint_vector_icon.h"
|
||||
#include "ui/gfx/text_constants.h"
|
||||
#include "ui/gfx/vector_icon_types.h"
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/controls/image_view.h"
|
||||
#include "ui/views/controls/label.h"
|
||||
#include "ui/views/layout/flex_layout_types.h"
|
||||
#include "ui/views/layout/flex_layout_view.h"
|
||||
#include "ui/views/layout/layout_types.h"
|
||||
#include "ui/views/metadata/view_factory.h"
|
||||
#include "ui/views/metadata/view_factory_internal.h"
|
||||
#include "ui/views/view.h"
|
||||
#include "ui/views/view_class_properties.h"
|
||||
|
||||
namespace ash::curtain {
|
||||
|
||||
namespace {
|
||||
|
||||
using views::Builder;
|
||||
using views::FlexLayoutView;
|
||||
using views::ImageView;
|
||||
using views::kFlexBehaviorKey;
|
||||
using views::kMarginsKey;
|
||||
using views::LayoutOrientation;
|
||||
constexpr char kRemoteManagementCurtainUrl[] = "chrome://security-curtain/";
|
||||
|
||||
constexpr gfx::Size kEnterpriseIconSize(40, 40);
|
||||
constexpr gfx::Size kLockImageSize(300, 300);
|
||||
|
||||
constexpr gfx::Insets kEnterpriseIconMargin = gfx::Insets::VH(20, 5);
|
||||
constexpr gfx::Insets kLockImageMargin = gfx::Insets::VH(20, 20);
|
||||
constexpr gfx::Insets kLeftSideMargins = gfx::Insets::VH(200, 100);
|
||||
constexpr gfx::Insets kRightSideMargins = gfx::Insets::VH(100, 100);
|
||||
|
||||
gfx::ImageSkia EnterpriseIcon(const ColorProvider& color_provider) {
|
||||
return gfx::CreateVectorIcon(
|
||||
chromeos::kEnterpriseIcon,
|
||||
color_provider.GetContentLayerColor(
|
||||
AshColorProvider::ContentLayerType::kIconColorPrimary));
|
||||
gfx::Size CalculateCurtainViewSize(const gfx::Size& size) {
|
||||
// TODO(b/271099991): Use correct margins once Oobe code has migrated to the
|
||||
// new UX style so we can use their code.
|
||||
const int horizontal_margin = size.width() / 10;
|
||||
const int vertical_margin = size.height() / 10;
|
||||
return gfx::Size(size.width() - 2 * horizontal_margin,
|
||||
size.height() - 2 * vertical_margin);
|
||||
}
|
||||
|
||||
gfx::ImageSkia LockImage(const ColorProvider& color_provider) {
|
||||
return gfx::CreateVectorIcon(
|
||||
kSystemTrayCapsLockIcon,
|
||||
AshColorProvider::Get()->GetContentLayerColor(
|
||||
AshColorProvider::ContentLayerType::kIconColorProminent));
|
||||
}
|
||||
|
||||
std::u16string TitleText() {
|
||||
return l10n_util::GetStringUTF16(IDS_ASH_CURTAIN_TITLE);
|
||||
}
|
||||
|
||||
std::u16string MessageText() {
|
||||
return l10n_util::GetStringUTF16(IDS_ASH_CURTAIN_DESCRIPTION);
|
||||
}
|
||||
|
||||
// A container that - when added as a child of a `FlexContainer` - will
|
||||
// automatically resize to take an equal share of the available space.
|
||||
class ResizingFlexContainer : public views::FlexLayoutView {
|
||||
public:
|
||||
ResizingFlexContainer() {
|
||||
// Tell our parent flex container that we want to be resized depending
|
||||
// on the available space.
|
||||
SetProperty(
|
||||
kFlexBehaviorKey,
|
||||
views::FlexSpecification{views::MinimumFlexSizeRule::kScaleToMinimum,
|
||||
views::MaximumFlexSizeRule::kUnbounded});
|
||||
}
|
||||
ResizingFlexContainer(const ResizingFlexContainer&) = delete;
|
||||
ResizingFlexContainer& operator=(const ResizingFlexContainer&) = delete;
|
||||
~ResizingFlexContainer() override = default;
|
||||
|
||||
// `views::FlexLayoutView` implementation:
|
||||
|
||||
gfx::Size CalculatePreferredSize() const override {
|
||||
// The parent Flex container will first grant each child as much space
|
||||
// as their preferred size, and then distributes all remaining space
|
||||
// equally among all children. So to ensure all children get exactly the
|
||||
// same space, we make them all report the same (small) preferred size.
|
||||
return gfx::Size(1, 1);
|
||||
}
|
||||
};
|
||||
|
||||
BEGIN_VIEW_BUILDER(, ResizingFlexContainer, views::FlexLayoutView)
|
||||
END_VIEW_BUILDER
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace ash::curtain
|
||||
|
||||
// Allow `ResizingContainer` to be used inside a view builder hierarchy
|
||||
// (`Builder<ResizingContainer>().SetXYZ()`).
|
||||
//
|
||||
// Must be in the global namespace.
|
||||
DEFINE_VIEW_BUILDER(, ash::curtain::ResizingFlexContainer)
|
||||
|
||||
namespace ash::curtain {
|
||||
|
||||
RemoteMaintenanceCurtainView::RemoteMaintenanceCurtainView() {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
RemoteMaintenanceCurtainView::~RemoteMaintenanceCurtainView() = default;
|
||||
|
||||
void RemoteMaintenanceCurtainView::Initialize() {
|
||||
const ColorProvider& color_provider = CHECK_DEREF(ColorProvider::Get());
|
||||
const int shelf_size = CHECK_DEREF(ShelfConfig::Get()).shelf_size();
|
||||
|
||||
// A flex rule forcing the view to maintain its fixed size.
|
||||
const views::FlexSpecification kFixedSize(
|
||||
views::MinimumFlexSizeRule::kPreferred,
|
||||
views::MaximumFlexSizeRule::kPreferred);
|
||||
|
||||
Builder<FlexLayoutView>(this)
|
||||
.SetOrientation(LayoutOrientation::kVertical)
|
||||
.SetBackground(
|
||||
views::CreateSolidBackground(color_provider.GetBaseLayerColor(
|
||||
ColorProvider::BaseLayerType::kOpaque)))
|
||||
.AddChildren(
|
||||
// Main content
|
||||
Builder<ResizingFlexContainer>()
|
||||
.SetOrientation(LayoutOrientation::kHorizontal)
|
||||
.AddChildren(
|
||||
// Left half of the screen
|
||||
Builder<ResizingFlexContainer>()
|
||||
.SetProperty(kMarginsKey, kLeftSideMargins)
|
||||
.SetOrientation(LayoutOrientation::kVertical)
|
||||
.AddChildren(
|
||||
// Enterprise icon
|
||||
Builder<ImageView>()
|
||||
.SetImage(EnterpriseIcon(color_provider))
|
||||
.SetImageSize(kEnterpriseIconSize)
|
||||
.SetProperty(kMarginsKey, kEnterpriseIconMargin)
|
||||
.SetHorizontalAlignment(
|
||||
ImageView::Alignment::kLeading),
|
||||
// Title
|
||||
Builder<views::Label>()
|
||||
.SetText(TitleText())
|
||||
.SetTextStyle(views::style::STYLE_EMPHASIZED)
|
||||
.SetTextContext(
|
||||
views::style::CONTEXT_DIALOG_TITLE)
|
||||
.SetHorizontalAlignment(
|
||||
gfx::HorizontalAlignment::ALIGN_LEFT)
|
||||
.SetMultiLine(true)
|
||||
.SetEnabledColor(
|
||||
color_provider.GetContentLayerColor(
|
||||
ColorProvider::ContentLayerType::
|
||||
kTextColorPrimary)),
|
||||
// Message
|
||||
Builder<views::Label>()
|
||||
.SetText(MessageText())
|
||||
.SetVerticalAlignment(
|
||||
gfx::VerticalAlignment::ALIGN_TOP)
|
||||
.SetHorizontalAlignment(
|
||||
gfx::HorizontalAlignment::ALIGN_LEFT)
|
||||
.SetMultiLine(true)
|
||||
.SetEnabledColor(
|
||||
color_provider.GetContentLayerColor(
|
||||
ColorProvider::ContentLayerType::
|
||||
kTextColorPrimary))),
|
||||
// Right half of the screen
|
||||
Builder<ResizingFlexContainer>()
|
||||
.SetProperty(kMarginsKey, kRightSideMargins)
|
||||
.AddChildren(
|
||||
Builder<ImageView>()
|
||||
.SetImage(LockImage(color_provider))
|
||||
.SetImageSize(kLockImageSize)
|
||||
.SetProperty(kMarginsKey, kLockImageMargin)
|
||||
.SetHorizontalAlignment(
|
||||
ImageView::Alignment::kCenter))),
|
||||
// Shelf
|
||||
Builder<View>()
|
||||
.SetPreferredSize(gfx::Size(0, shelf_size))
|
||||
.SetProperty(kFlexBehaviorKey, kFixedSize))
|
||||
.BuildChildren();
|
||||
void RemoteMaintenanceCurtainView::OnBoundsChanged(const gfx::Rect&) {
|
||||
UpdateChildrenSize(size());
|
||||
}
|
||||
|
||||
BEGIN_METADATA(RemoteMaintenanceCurtainView, views::FlexLayoutView)
|
||||
END_METADATA
|
||||
void RemoteMaintenanceCurtainView::UpdateChildrenSize(
|
||||
const gfx::Size& new_size) {
|
||||
wallpaper_view_->SetPreferredSize(new_size);
|
||||
curtain_view_->SetPreferredSize(CalculateCurtainViewSize(new_size));
|
||||
}
|
||||
|
||||
void RemoteMaintenanceCurtainView::Initialize() {
|
||||
layout_ = SetLayoutManager(std::make_unique<StackLayout>());
|
||||
|
||||
AddWallpaper();
|
||||
AddCurtainWebView();
|
||||
}
|
||||
|
||||
void RemoteMaintenanceCurtainView::AddWallpaper() {
|
||||
// Add a copy of the wallpaper above the security curtain, since UX wants
|
||||
// to see a blurred wallpaper but we can't expose the real wallpaper as that
|
||||
// would require the security curtain to be translucent which would defeat
|
||||
// its whole purpose.
|
||||
DCHECK(!wallpaper_view_);
|
||||
wallpaper_view_ = AddChildView(
|
||||
std::make_unique<WallpaperView>(wallpaper_constants::kLockLoginBlur));
|
||||
}
|
||||
|
||||
void RemoteMaintenanceCurtainView::AddCurtainWebView() {
|
||||
DCHECK(!curtain_view_);
|
||||
curtain_view_ =
|
||||
AddChildView(AshWebViewFactory::Get()->Create(AshWebView::InitParams()));
|
||||
layout_->SetVerticalAlignmentForView(curtain_view_,
|
||||
StackLayout::VerticalAlignment::kCenter);
|
||||
|
||||
// Load the actual security curtain content.
|
||||
curtain_view_->Navigate(GURL(kRemoteManagementCurtainUrl));
|
||||
}
|
||||
|
||||
} // namespace ash::curtain
|
||||
|
@ -6,15 +6,25 @@
|
||||
#define ASH_CURTAIN_REMOTE_MAINTENANCE_CURTAIN_VIEW_H_
|
||||
|
||||
#include "ash/ash_export.h"
|
||||
#include "ui/base/metadata/metadata_header_macros.h"
|
||||
#include "ui/views/layout/flex_layout_view.h"
|
||||
#include "base/allocator/partition_allocator/pointers/raw_ptr.h"
|
||||
#include "ui/views/view.h"
|
||||
|
||||
namespace ash {
|
||||
class AshWebView;
|
||||
class StackLayout;
|
||||
} // namespace ash
|
||||
|
||||
namespace gfx {
|
||||
class Rect;
|
||||
class Size;
|
||||
} // namespace gfx
|
||||
|
||||
namespace ash::curtain {
|
||||
|
||||
// The root view shown as the security curtain overlay when the security curtain
|
||||
// is created by an enterprise admin through the 'start crd session' remote
|
||||
// command.
|
||||
class ASH_EXPORT RemoteMaintenanceCurtainView : public views::FlexLayoutView {
|
||||
class ASH_EXPORT RemoteMaintenanceCurtainView : public views::View {
|
||||
public:
|
||||
RemoteMaintenanceCurtainView();
|
||||
RemoteMaintenanceCurtainView(const RemoteMaintenanceCurtainView&) = delete;
|
||||
@ -22,10 +32,19 @@ class ASH_EXPORT RemoteMaintenanceCurtainView : public views::FlexLayoutView {
|
||||
delete;
|
||||
~RemoteMaintenanceCurtainView() override;
|
||||
|
||||
METADATA_HEADER(RemoteMaintenanceCurtainView);
|
||||
|
||||
private:
|
||||
// `views::View` implementation:
|
||||
void OnBoundsChanged(const gfx::Rect&) override;
|
||||
|
||||
void UpdateChildrenSize(const gfx::Size& new_size);
|
||||
|
||||
void Initialize();
|
||||
void AddWallpaper();
|
||||
void AddCurtainWebView();
|
||||
|
||||
raw_ptr<StackLayout> layout_ = nullptr;
|
||||
raw_ptr<AshWebView> curtain_view_ = nullptr;
|
||||
raw_ptr<views::View> wallpaper_view_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace ash::curtain
|
||||
|
@ -6648,4 +6648,13 @@ Your <ph name="DEVICE_TYPE">{0}<ex>Chromebook</ex></ph> will be locked now.
|
||||
<message name="IDS_OFFICE_FALLBACK_INSTRUCTIONS" desc="Office Fallback dialog instructions for the choices (buttons) the user has available to open the office file.">
|
||||
Choose "Try again", or choose "Open in offline editor" to use limited view and editing options.
|
||||
</message>
|
||||
|
||||
<!-- security curtain -->
|
||||
<message name="IDS_SECURITY_CURTAIN_TITLE" desc="Title text displayed to inform the user a remote admin has taken control of the ChromeOs device.">
|
||||
Your administrator is controlling your device
|
||||
</message>
|
||||
<message name="IDS_SECURITY_CURTAIN_DESCRIPTION" desc="Detailed description displayed to inform the user a remote admin has taken control of the ChromeOs device.">
|
||||
Your administrator has logged in to look into an issue. You can continue to use the device after the administrator gives the control back to you.
|
||||
</message>
|
||||
|
||||
</grit-part>
|
||||
|
@ -0,0 +1 @@
|
||||
344f76c78773402b51bc14353489b58efc19569a
|
@ -0,0 +1 @@
|
||||
344f76c78773402b51bc14353489b58efc19569a
|
@ -0,0 +1,27 @@
|
||||
# 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.
|
||||
|
||||
import("//ui/webui/resources/tools/build_webui.gni")
|
||||
|
||||
assert(is_chromeos_ash)
|
||||
|
||||
build_webui("build") {
|
||||
grd_prefix = "remote_maintenance_curtain"
|
||||
|
||||
static_files = [
|
||||
"main.html",
|
||||
|
||||
# Vector resources
|
||||
"images/admin_control_dark.svg",
|
||||
"images/admin_control_light.svg",
|
||||
]
|
||||
|
||||
# Files added here must have a corresponding .html file
|
||||
web_component_files = [ "curtain_screen.ts" ]
|
||||
|
||||
ts_deps = [
|
||||
"//third_party/polymer/v3_0:library",
|
||||
"//ui/webui/resources/js:build_ts",
|
||||
]
|
||||
}
|
@ -0,0 +1 @@
|
||||
file://ash/curtain/OWNERS
|
@ -0,0 +1,21 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<style include="oobe-common-styles oobe-dialog-host-styles"></style>
|
||||
|
||||
<oobe-adaptive-dialog id="mainCurtainDialog" role="dialog"
|
||||
aria-label="$i18n{curtainTitle}">
|
||||
<iron-icon slot="icon" icon="oobe-32:enterprise"></iron-icon>
|
||||
<h1 slot="title">$i18n{curtainTitle}</h1>
|
||||
<div slot="subtitle">$i18n{curtainDescription}</div>
|
||||
<div slot="content" class="flex layout vertical center center-justified">
|
||||
<picture>
|
||||
<source srcset="images/admin_control_dark.svg"
|
||||
media="(prefers-color-scheme: dark)" class="oobe-illustration">
|
||||
<img class="illustration" src="images/admin_control_light.svg">
|
||||
</picture>
|
||||
</div>
|
||||
</oobe-adaptive-dialog>
|
@ -0,0 +1,73 @@
|
||||
// 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.
|
||||
|
||||
import '//resources/polymer/v3_0/iron-icon/iron-icon.js';
|
||||
import '//resources/polymer/v3_0/iron-media-query/iron-media-query.js';
|
||||
import './components/common_styles/oobe_dialog_host_styles.css.js';
|
||||
import './components/dialogs/oobe_adaptive_dialog.js';
|
||||
import './components/oobe_icons.html.js';
|
||||
import './components/common_styles/oobe_common_styles.css.js';
|
||||
|
||||
import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
|
||||
|
||||
import {getTemplate} from './curtain_screen.html.js';
|
||||
|
||||
function setDialogSizeAndOrientation() {
|
||||
document.documentElement.style.setProperty(
|
||||
'--oobe-oobe-dialog-height-base', window.innerHeight + 'px');
|
||||
document.documentElement.style.setProperty(
|
||||
'--oobe-oobe-dialog-width-base', window.innerWidth + 'px');
|
||||
|
||||
// Screen orientation value needs to be kept up-to-date.
|
||||
document.documentElement.setAttribute(
|
||||
'orientation',
|
||||
window.innerWidth > window.innerHeight ? 'horizontal' : 'vertical');
|
||||
}
|
||||
|
||||
// TODO(b/274059668): Remove when OOBE is migrated to TS.
|
||||
type OobeAdaptiveDialog = HTMLElement&{
|
||||
onBeforeShow(): void,
|
||||
};
|
||||
|
||||
// Inform the compiler that the`this.$.mainCurtainDialog` statement below
|
||||
// returns an element of type `OobeAdaptiveDialog`.
|
||||
interface CurtainScreenElement {
|
||||
$: {
|
||||
mainCurtainDialog: OobeAdaptiveDialog,
|
||||
};
|
||||
}
|
||||
|
||||
class CurtainScreenElement extends PolymerElement {
|
||||
static get is() {
|
||||
return 'curtain-screen' as const;
|
||||
}
|
||||
|
||||
static get template() {
|
||||
return getTemplate();
|
||||
}
|
||||
|
||||
override ready() {
|
||||
super.ready();
|
||||
this.$.mainCurtainDialog.onBeforeShow();
|
||||
setDialogSizeAndOrientation();
|
||||
}
|
||||
|
||||
override connectedCallback() {
|
||||
super.connectedCallback();
|
||||
window.addEventListener('resize', setDialogSizeAndOrientation);
|
||||
}
|
||||
|
||||
override disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
window.removeEventListener('resize', setDialogSizeAndOrientation);
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
[CurtainScreenElement.is]: CurtainScreenElement;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(CurtainScreenElement.is, CurtainScreenElement);
|
1
chrome/browser/resources/chromeos/remote_maintenance_curtain/images/admin_control_dark.svg
Normal file
1
chrome/browser/resources/chromeos/remote_maintenance_curtain/images/admin_control_dark.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width="512" height="260" viewBox="0 0 512 260" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M200 229v-58.398c0-20.72-16.76-37.602-37.5-37.602-20.663 0-37.5 16.806-37.5 37.602V229" stroke="#5BB974" stroke-width="2" stroke-miterlimit="10"/><path d="M302 117v11m6-16v16" stroke="#FCC934" stroke-width="2" stroke-miterlimit="10"/><path d="M204 35v10m-6-14v14" stroke="#669DF6" stroke-width="2" stroke-miterlimit="10"/><path d="M267.923 229H178V58.308C178 51 183.918 45 191.296 45h63.408C262.005 45 268 50.923 268 58.308V229h-.077Z" fill="#8AB4F8" fill-opacity=".4"/><path d="M378.291 126h-82.658c-4.813 0-8.633 3.938-8.633 8.725V229h100v-94.275a8.686 8.686 0 0 0-8.709-8.725Z" fill="#669DF6"/><path d="M228 229v-8.39c0-2.569 2.093-4.61 4.729-4.61h10.542c2.636 0 4.729 2.041 4.729 4.61V229" stroke="#669DF6" stroke-width="2" stroke-miterlimit="10"/><path d="M363 229v-9.994c0-1.653-1.385-3.006-3.077-3.006h-7.846c-1.692 0-3.077 1.353-3.077 3.006V229m-34 0v-6.744h-7.518v-7.365h-7.441v-8.527h-6.904V199H287" stroke="#323336" stroke-width="2" stroke-miterlimit="10"/><path d="M287 199h-10v30" stroke="#8AB4F8" stroke-opacity=".4" stroke-width="2" stroke-miterlimit="10"/><path fill-rule="evenodd" clip-rule="evenodd" d="M178 137.457v-2.199c13.556 5.988 23 19.586 23 35.344V229h-2v-58.398c0-14.63-8.583-27.292-21-33.145Z" fill="#323336"/><path d="M225 62h-7v12h7V62Zm0 25h-7v12h7V87Zm0 25h-7v11h7v-11Z" fill="#669DF6" stroke="#669DF6" stroke-width="2" stroke-miterlimit="10"/><path d="M225 137h-7v11h7v-11Z" fill="#323336" stroke="#323336" stroke-width="2" stroke-miterlimit="10"/><path d="M225 161h-7v12h7v-12Zm0 25h-7v12h7v-12Zm16-124h-6v12h6V62Zm0 25h-6v12h6V87Zm0 25h-6v11h6v-11Zm0 25h-6v11h6v-11Zm0 24h-6v12h6v-12Z" fill="#669DF6" stroke="#669DF6" stroke-width="2" stroke-miterlimit="10"/><path d="M241 186h-6v12h6v-12Z" fill="#323336" stroke="#323336" stroke-width="2" stroke-miterlimit="10"/><path d="M258 62h-7v12h7V62Z" fill="#669DF6" stroke="#669DF6" stroke-width="2" stroke-miterlimit="10"/><path d="M258 87h-7v12h7V87Z" fill="#323336" stroke="#323336" stroke-width="2" stroke-miterlimit="10"/><path d="M258 112h-7v11h7v-11Zm0 25h-7v11h7v-11Zm0 24h-7v12h7v-12Zm0 25h-7v12h7v-12Z" fill="#669DF6" stroke="#669DF6" stroke-width="2" stroke-miterlimit="10"/><path d="M326 137h61m-61 11h61m-61 12h61m-61 12h61m-61 11h61m-61 12h61m-61 12h61m-61-81v103" stroke="#323336" stroke-width="2" stroke-miterlimit="10"/><path stroke="#669DF6" stroke-width="2" stroke-linecap="round" d="M36 228h440"/></svg>
|
After (image error) Size: 2.5 KiB |
1
chrome/browser/resources/chromeos/remote_maintenance_curtain/images/admin_control_light.svg
Normal file
1
chrome/browser/resources/chromeos/remote_maintenance_curtain/images/admin_control_light.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width="512" height="260" viewBox="0 0 512 260" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M200 229v-58.398c0-20.72-16.76-37.602-37.5-37.602-20.663 0-37.5 16.806-37.5 37.602V229" stroke="#34A853" stroke-width="2" stroke-miterlimit="10"/><path d="M302 117v11m6-16v16" stroke="#FBBC04" stroke-width="2" stroke-miterlimit="10"/><path d="M204 35v11m-6-15v15" stroke="#4285F4" stroke-width="2" stroke-miterlimit="10"/><path d="M267.923 229H178V58.308C178 51 183.918 45 191.296 45h63.408C262.005 45 268 50.923 268 58.308V229h-.077Z" fill="#D2E3FC"/><path d="M378.291 126h-82.658c-4.813 0-8.633 3.938-8.633 8.725V229h100v-94.275a8.686 8.686 0 0 0-8.709-8.725Z" fill="#4285F4"/><path d="M228 229v-8.39c0-2.569 2.093-4.61 4.729-4.61h10.542c2.636 0 4.729 2.041 4.729 4.61V229" stroke="#4285F4" stroke-width="2" stroke-miterlimit="10"/><path d="M363 229v-9.994c0-1.653-1.385-3.006-3.077-3.006h-7.846c-1.692 0-3.077 1.353-3.077 3.006V229" stroke="#D2E3FC" stroke-width="2" stroke-miterlimit="10"/><path d="M315 229v-6.744h-7.518v-7.365h-7.441v-8.527h-6.904V199H287" stroke="#fff" stroke-width="2" stroke-miterlimit="10"/><path d="M287 199h-10v30" stroke="#D2E3FC" stroke-width="2" stroke-miterlimit="10"/><path fill-rule="evenodd" clip-rule="evenodd" d="M178 137.457v-2.2c13.556 5.989 23 19.587 23 35.345V229h-2v-58.398c0-14.63-8.583-27.293-21-33.145Z" fill="#fff"/><path d="M225 62h-7v12h7V62Zm0 25h-7v12h7V87Zm0 25h-7v11h7v-11Z" fill="#4285F4" stroke="#4285F4" stroke-width="2" stroke-miterlimit="10"/><path d="M225 137h-7v11h7v-11Z" fill="#fff" stroke="#fff" stroke-width="2" stroke-miterlimit="10"/><path d="M225 161h-7v12h7v-12Zm0 25h-7v12h7v-12Zm16-124h-6v12h6V62Zm0 25h-6v12h6V87Zm0 25h-6v11h6v-11Zm0 25h-6v11h6v-11Zm0 24h-6v12h6v-12Z" fill="#4285F4" stroke="#4285F4" stroke-width="2" stroke-miterlimit="10"/><path d="M241 186h-6v12h6v-12Z" fill="#fff" stroke="#fff" stroke-width="2" stroke-miterlimit="10"/><path d="M258 62h-7v12h7V62Z" fill="#4285F4" stroke="#4285F4" stroke-width="2" stroke-miterlimit="10"/><path d="M258 87h-7v12h7V87Z" fill="#fff" stroke="#fff" stroke-width="2" stroke-miterlimit="10"/><path d="M258 112h-7v11h7v-11Zm0 25h-7v11h7v-11Zm0 24h-7v12h7v-12Zm0 25h-7v12h7v-12Z" fill="#4285F4" stroke="#4285F4" stroke-width="2" stroke-miterlimit="10"/><path d="M326 137h61m-61 11h61m-61 12h61m-61 12h61m-61 11h61m-61 12h61m-61 12h61m-61-81v103" stroke="#D2E3FC" stroke-width="2" stroke-miterlimit="10"/><path stroke="#4285F4" stroke-width="2" stroke-linecap="round" d="M36 228h440"/></svg>
|
After (image error) Size: 2.5 KiB |
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<!doctype html>
|
||||
<html dir="$i18n{textdirection}" lang="$i18n{language}">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<link rel="stylesheet"
|
||||
href="chrome://resources/chromeos/colors/cros_styles.css">
|
||||
<link rel="stylesheet" href="./oobe.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<curtain-screen></curtain-screen>
|
||||
<script type="module" src='./curtain_screen.js'></script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -2964,6 +2964,8 @@ static_library("ui") {
|
||||
"webui/ash/parent_access/parent_access_ui_handler_impl.h",
|
||||
"webui/ash/power_ui.cc",
|
||||
"webui/ash/power_ui.h",
|
||||
"webui/ash/remote_maintenance_curtain_ui.cc",
|
||||
"webui/ash/remote_maintenance_curtain_ui.h",
|
||||
"webui/ash/set_time_ui.cc",
|
||||
"webui/ash/set_time_ui.h",
|
||||
"webui/ash/shimless_rma_dialog.cc",
|
||||
@ -3271,6 +3273,7 @@ static_library("ui") {
|
||||
"//chrome/browser/resources:internet_detail_dialog_resources",
|
||||
"//chrome/browser/resources/chromeos:multidevice_setup_resources",
|
||||
"//chrome/browser/resources/chromeos/cloud_upload:resources",
|
||||
"//chrome/browser/resources/chromeos/remote_maintenance_curtain:resources",
|
||||
"//chrome/browser/ui/quick_answers",
|
||||
"//chrome/browser/ui/webui/ash/add_supervision:mojo_bindings",
|
||||
"//chrome/browser/ui/webui/ash/audio:mojo_bindings",
|
||||
|
41
chrome/browser/ui/webui/ash/remote_maintenance_curtain_ui.cc
Normal file
41
chrome/browser/ui/webui/ash/remote_maintenance_curtain_ui.cc
Normal file
@ -0,0 +1,41 @@
|
||||
// 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 "chrome/browser/ui/webui/ash/remote_maintenance_curtain_ui.h"
|
||||
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "chrome/browser/ui/webui/ash/login/oobe_ui.h"
|
||||
#include "chrome/browser/ui/webui/webui_util.h"
|
||||
#include "chrome/common/webui_url_constants.h"
|
||||
#include "chrome/grit/generated_resources.h"
|
||||
#include "chrome/grit/remote_maintenance_curtain_resources.h"
|
||||
#include "chrome/grit/remote_maintenance_curtain_resources_map.h"
|
||||
#include "content/public/browser/web_ui_data_source.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
RemoteMaintenanceCurtainUI::RemoteMaintenanceCurtainUI(content::WebUI* web_ui)
|
||||
: content::WebUIController(web_ui) {
|
||||
content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
|
||||
Profile::FromWebUI(web_ui), chrome::kChromeUIRemoteManagementCurtainHost);
|
||||
|
||||
webui::SetupWebUIDataSource(
|
||||
source,
|
||||
base::make_span(kRemoteMaintenanceCurtainResources,
|
||||
kRemoteMaintenanceCurtainResourcesSize),
|
||||
IDR_REMOTE_MAINTENANCE_CURTAIN_MAIN_HTML);
|
||||
|
||||
// Add OOBE resources so our WebUI can find the OOBE WebUI resources (css,
|
||||
// javascript files, ...) at runtime.
|
||||
OobeUI::AddOobeComponents(source);
|
||||
|
||||
// Add localized strings
|
||||
source->AddLocalizedString("curtainTitle", IDS_SECURITY_CURTAIN_TITLE);
|
||||
source->AddLocalizedString("curtainDescription",
|
||||
IDS_SECURITY_CURTAIN_DESCRIPTION);
|
||||
}
|
||||
|
||||
WEB_UI_CONTROLLER_TYPE_IMPL(RemoteMaintenanceCurtainUI)
|
||||
|
||||
} // namespace ash
|
28
chrome/browser/ui/webui/ash/remote_maintenance_curtain_ui.h
Normal file
28
chrome/browser/ui/webui/ash/remote_maintenance_curtain_ui.h
Normal file
@ -0,0 +1,28 @@
|
||||
// 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.
|
||||
|
||||
#ifndef CHROME_BROWSER_UI_WEBUI_ASH_REMOTE_MAINTENANCE_CURTAIN_UI_H_
|
||||
#define CHROME_BROWSER_UI_WEBUI_ASH_REMOTE_MAINTENANCE_CURTAIN_UI_H_
|
||||
|
||||
#include "content/public/browser/web_ui_controller.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
class RemoteMaintenanceCurtainUI : public content::WebUIController {
|
||||
public:
|
||||
explicit RemoteMaintenanceCurtainUI(content::WebUI* web_ui);
|
||||
|
||||
RemoteMaintenanceCurtainUI(const RemoteMaintenanceCurtainUI&) = delete;
|
||||
RemoteMaintenanceCurtainUI& operator=(const RemoteMaintenanceCurtainUI&) =
|
||||
delete;
|
||||
|
||||
~RemoteMaintenanceCurtainUI() override = default;
|
||||
|
||||
private:
|
||||
WEB_UI_CONTROLLER_TYPE_DECL();
|
||||
};
|
||||
|
||||
} // namespace ash
|
||||
|
||||
#endif // CHROME_BROWSER_UI_WEBUI_ASH_REMOTE_MAINTENANCE_CURTAIN_UI_H_
|
@ -290,6 +290,7 @@
|
||||
#include "chrome/browser/ui/webui/ash/notification_tester/notification_tester_ui.h"
|
||||
#include "chrome/browser/ui/webui/ash/parent_access/parent_access_ui.h"
|
||||
#include "chrome/browser/ui/webui/ash/power_ui.h"
|
||||
#include "chrome/browser/ui/webui/ash/remote_maintenance_curtain_ui.h"
|
||||
#include "chrome/browser/ui/webui/ash/set_time_ui.h"
|
||||
#include "chrome/browser/ui/webui/ash/slow_trace_ui.h"
|
||||
#include "chrome/browser/ui/webui/ash/slow_ui.h"
|
||||
@ -1012,6 +1013,9 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
if (url.host_piece() == chrome::kChromeUIRemoteManagementCurtainHost) {
|
||||
return &NewWebUI<ash::RemoteMaintenanceCurtainUI>;
|
||||
}
|
||||
if (url.host_piece() == ash::kChromeUIDiagnosticsAppHost) {
|
||||
return &NewWebUI<ash::DiagnosticsDialogUI>;
|
||||
}
|
||||
|
@ -308,6 +308,7 @@ template("chrome_extra_paks") {
|
||||
"$root_gen_dir/chrome/oobe_unconditional_resources.pak",
|
||||
"$root_gen_dir/chrome/os_settings_resources.pak",
|
||||
"$root_gen_dir/chrome/password_change_resources.pak",
|
||||
"$root_gen_dir/chrome/remote_maintenance_curtain_resources.pak",
|
||||
"$root_gen_dir/chrome/supervision_resources.pak",
|
||||
"$root_gen_dir/chrome/vc_tray_tester_resources.pak",
|
||||
"$root_gen_dir/chromeos/ash/ash_resources.pak",
|
||||
@ -383,6 +384,7 @@ template("chrome_extra_paks") {
|
||||
"//chrome/browser/resources/chromeos/network_ui:resources",
|
||||
"//chrome/browser/resources/chromeos/notification_tester:resources",
|
||||
"//chrome/browser/resources/chromeos/password_change:resources",
|
||||
"//chrome/browser/resources/chromeos/remote_maintenance_curtain:resources",
|
||||
"//chrome/browser/resources/chromeos/supervision:resources",
|
||||
"//chrome/browser/resources/chromeos/vc_tray_tester:resources",
|
||||
"//chrome/browser/resources/nearby_internals:resources",
|
||||
|
@ -377,6 +377,7 @@ const char kChromeUIPasswordChangeUrl[] = "chrome://password-change";
|
||||
const char kChromeUIPrintManagementUrl[] = "chrome://print-management";
|
||||
const char kChromeUIPowerHost[] = "power";
|
||||
const char kChromeUIPowerUrl[] = "chrome://power";
|
||||
const char kChromeUIRemoteManagementCurtainHost[] = "security-curtain";
|
||||
const char kChromeUIScanningAppURL[] = "chrome://scanning";
|
||||
const char kChromeUIScreenlockIconHost[] = "screenlock-icon";
|
||||
const char kChromeUIScreenlockIconURL[] = "chrome://screenlock-icon/";
|
||||
@ -482,8 +483,9 @@ bool IsSystemWebUIHost(base::StringPiece host) {
|
||||
#endif // BUILDFLAG(PLATFORM_CFM)
|
||||
};
|
||||
for (const char* h : kHosts) {
|
||||
if (host == h)
|
||||
if (host == h) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -352,6 +352,7 @@ extern const char kChromeUIPasswordChangeUrl[];
|
||||
extern const char kChromeUIPrintManagementUrl[];
|
||||
extern const char kChromeUIPowerHost[];
|
||||
extern const char kChromeUIPowerUrl[];
|
||||
extern const char kChromeUIRemoteManagementCurtainHost[];
|
||||
extern const char kChromeUIScanningAppURL[];
|
||||
extern const char kChromeUIScreenlockIconHost[];
|
||||
extern const char kChromeUIScreenlockIconURL[];
|
||||
|
@ -151,6 +151,10 @@
|
||||
"META": {"sizes": {"includes": [50]}},
|
||||
"includes": [1380],
|
||||
},
|
||||
"<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/chromeos/remote_maintenance_curtain/resources.grd": {
|
||||
"META": {"sizes": {"includes": [10]}},
|
||||
"includes": [1381],
|
||||
},
|
||||
"<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/chromeos/supervision/resources.grd": {
|
||||
"META": {"sizes": {"includes": [10],}},
|
||||
"includes": [1383],
|
||||
|
Reference in New Issue
Block a user