Skip to content

Commit

Permalink
personalization: highlight selected preset backlight color
Browse files Browse the repository at this point in the history
Add KeyboardBacklightObserver interface to notify the JS side the
selected backlight color. This only highlights the selected preset color
options currently. The capability to select and highlight wallpaper
extracted color will be done in a subsequent CL.

BUG=b/227374197
TEST=browser_tests
--gtest_filter="*PersonalizationAppKeyboardBacklight*"
TEST=unit_tests
--gtest_filter="*PersonalizationAppKeyboardBacklightProviderImpl*"

Cq-Include-Trybots: luci.chrome.try:linux-chromeos-chrome
Change-Id: I7ffe5e37443a6304242dbe1648941608a79a313f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3614652
Reviewed-by: Sam McNally <sammc@chromium.org>
Reviewed-by: Jeffrey Young <cowmoo@chromium.org>
Commit-Queue: Jason Thai <jasontt@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1001333}
  • Loading branch information
Jason Thai authored and Chromium LUCI CQ committed May 10, 2022
1 parent 4d69c0f commit 97fdff7
Show file tree
Hide file tree
Showing 12 changed files with 223 additions and 7 deletions.
11 changes: 11 additions & 0 deletions ash/webui/personalization_app/mojom/personalization_app.mojom
Original file line number Diff line number Diff line change
Expand Up @@ -540,8 +540,19 @@ enum BacklightColor {
kRainbow = 100,
};

// Receives information whenever there are keyboard backlight related changes
// such as backlight colors.
interface KeyboardBacklightObserver {
// Notifies the JS side about the current state of the backlight color.
OnBacklightColorChanged(BacklightColor color);
};

// Provides APIs to expose keyboard backlight settings.
interface KeyboardBacklightProvider {
// Binds a listener to start receiving updates on backlight color changes.
SetKeyboardBacklightObserver(pending_remote<KeyboardBacklightObserver>
observer);

// Sets the backlight color.
SetBacklightColor(BacklightColor backlight_color);
};
1 change: 1 addition & 0 deletions ash/webui/personalization_app/resources/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ non_web_component_files = [
"trusted/keyboard_backlight/keyboard_backlight_actions.ts",
"trusted/keyboard_backlight/keyboard_backlight_controller.ts",
"trusted/keyboard_backlight/keyboard_backlight_interface_provider.ts",
"trusted/keyboard_backlight/keyboard_backlight_observer.ts",
"trusted/keyboard_backlight/keyboard_backlight_reducers.ts",
"trusted/keyboard_backlight/keyboard_backlight_state.ts",
"trusted/personalization_actions.ts",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,11 @@
width: 24px;
}

.color-inner-container iron-icon {
/* TODO(b/227374197): Show the icon for selected color. */
.color-container:not([aria-selected='true']) .color-inner-container iron-icon {
display: none;
}

.color-inner-container iron-icon {
padding-block-start: 5px;
padding-inline-start: 5px;
--iron-icon-fill-color: var(--cros-text-color-primary);
Expand Down Expand Up @@ -101,8 +103,9 @@
<div class="divider"></div>
<template is="dom-repeat" items="[[presetColorIds_]]" as="presetColorId">
<div id$="[[presetColorId]]" class="color-container"
on-click="onPresetColorSelected_" on-keypress="onPresetColorSelected_"
aria-label$="[[getPresetColorAriaLabel_(presetColorId)]]"
on-click="onPresetColorSelected_" on-keypress="onPresetColorSelected_">
aria-selected$="[[getPresetColorAriaSelected_(presetColorId, presetColors_, backlightColor_)]]">
<div class="color-inner-container"
style$="[[getColorInnerContainerStyle_(presetColorId, presetColors_)]]">
<paper-ripple class="circle"></paper-ripple>
Expand All @@ -112,7 +115,8 @@
</template>
<div id$="[[rainbowColorId_]]" class="color-container" tabindex="0"
on-click="onRainbowColorSelected_" on-keypress="onRainbowColorSelected_"
aria-label="$i18n{rainbowColor}">
aria-label="$i18n{rainbowColor}"
aria-selected$="[[getRainbowColorAriaSelected(backlightColor_)]]">
<div class="color-inner-container"
style$="[[getColorInnerContainerStyle_(rainbowColorId_, presetColors_)]]">
<paper-ripple class="circle"></paper-ripple>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {WithPersonalizationStore} from '../personalization_store.js';
import {setBacklightColor} from './keyboard_backlight_controller.js';
import {getTemplate} from './keyboard_backlight_element.html.js';
import {getKeyboardBacklightProvider} from './keyboard_backlight_interface_provider.js';
import {KeyboardBacklightObserver} from './keyboard_backlight_observer.js';


/**
Expand Down Expand Up @@ -91,6 +92,7 @@ export class KeyboardBacklight extends WithPersonalizationStore {

override connectedCallback() {
super.connectedCallback();
KeyboardBacklightObserver.initKeyboardBacklightObserverIfNeeded();
this.watch<KeyboardBacklight['backlightColor_']>(
'backlightColor_', state => state.keyboardBacklight.backlightColor);
this.updateFromStore();
Expand Down Expand Up @@ -194,6 +196,19 @@ export class KeyboardBacklight extends WithPersonalizationStore {
private getPresetColorAriaLabel_(presetColorId: string): string {
return this.i18n(presetColorId);
}

private getPresetColorAriaSelected_(
colorId: string, colors: Record<string, ColorInfo>,
selectedColor: BacklightColor) {
if (!colorId || !colors[colorId]) {
return 'false';
}
return (colors[colorId].enumVal === selectedColor).toString();
}

private getRainbowColorAriaSelected(selectedColor: BacklightColor) {
return (selectedColor === BacklightColor.kRainbow).toString();
}
}

customElements.define(KeyboardBacklight.is, KeyboardBacklight);
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2022 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.

import {BacklightColor, KeyboardBacklightObserverInterface, KeyboardBacklightObserverReceiver, KeyboardBacklightProviderInterface} from '../personalization_app.mojom-webui.js';
import {PersonalizationStore} from '../personalization_store.js';

import {setBacklightColorAction} from './keyboard_backlight_actions.js';
import {getKeyboardBacklightProvider} from './keyboard_backlight_interface_provider.js';

/** @fileoverview listens for updates on keyboard backlight settings changes. */

let instance: KeyboardBacklightObserver|null = null;

/**
* Observes keyboard backlight changes and saves updates to
* PersonalizationStore.
*/
export class KeyboardBacklightObserver implements
KeyboardBacklightObserverInterface {
static initKeyboardBacklightObserverIfNeeded(): void {
if (!instance) {
instance = new KeyboardBacklightObserver();
}
}

static shutdown() {
if (instance) {
instance.receiver_.$.close();
instance = null;
}
}

receiver_: KeyboardBacklightObserverReceiver =
this.initReceiver_(getKeyboardBacklightProvider());

private initReceiver_(KeyboardBacklightProvider:
KeyboardBacklightProviderInterface):
KeyboardBacklightObserverReceiver {
const receiver = new KeyboardBacklightObserverReceiver(this);
KeyboardBacklightProvider.setKeyboardBacklightObserver(
receiver.$.bindNewPipeAndPassRemote());
return receiver;
}

onBacklightColorChanged(backlightColor: BacklightColor): void {
const store = PersonalizationStore.getInstance();
store.dispatch(setBacklightColorAction(backlightColor));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ export {IFrameApi} from './iframe_api.js';
export {KeyboardBacklightActionName, KeyboardBacklightActions, SetBacklightColorAction, setBacklightColorAction} from './keyboard_backlight/keyboard_backlight_actions.js';
export {KeyboardBacklight} from './keyboard_backlight/keyboard_backlight_element.js';
export {setKeyboardBacklightProviderForTesting} from './keyboard_backlight/keyboard_backlight_interface_provider.js';
export {KeyboardBacklightObserver} from './keyboard_backlight/keyboard_backlight_observer.js';
export {Actions, DismissErrorAction, dismissErrorAction, PersonalizationActionName, SetErrorAction} from './personalization_actions.js';
export {AmbientModeAlbum, AmbientObserverInterface, AmbientObserverRemote, AmbientProviderInterface, AnimationTheme, BacklightColor, CurrentWallpaper, DefaultUserImage, FetchGooglePhotosAlbumsResponse, FetchGooglePhotosPhotosResponse, GooglePhotosAlbum, GooglePhotosEnablementState, GooglePhotosPhoto, KeyboardBacklightProviderInterface, OnlineImageType, TemperatureUnit, ThemeObserverInterface, ThemeObserverRemote, ThemeProviderInterface, TopicSource, UserImage, UserImageObserverInterface, UserImageObserverRemote, UserInfo, UserProviderInterface, WallpaperCollection, WallpaperImage, WallpaperLayout, WallpaperObserverInterface, WallpaperObserverRemote, WallpaperProviderInterface, WallpaperType} from './personalization_app.mojom-webui.js';
export {AmbientModeAlbum, AmbientObserverInterface, AmbientObserverRemote, AmbientProviderInterface, AnimationTheme, BacklightColor, CurrentWallpaper, DefaultUserImage, FetchGooglePhotosAlbumsResponse, FetchGooglePhotosPhotosResponse, GooglePhotosAlbum, GooglePhotosEnablementState, GooglePhotosPhoto, KeyboardBacklightObserverInterface, KeyboardBacklightObserverRemote, KeyboardBacklightProviderInterface, OnlineImageType, TemperatureUnit, ThemeObserverInterface, ThemeObserverRemote, ThemeProviderInterface, TopicSource, UserImage, UserImageObserverInterface, UserImageObserverRemote, UserInfo, UserProviderInterface, WallpaperCollection, WallpaperImage, WallpaperLayout, WallpaperObserverInterface, WallpaperObserverRemote, WallpaperProviderInterface, WallpaperType} from './personalization_app.mojom-webui.js';
export {PersonalizationBreadcrumb} from './personalization_breadcrumb_element.js';
export {PersonalizationMain} from './personalization_main_element.js';
export {reduce} from './personalization_reducers.js';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class FakePersonalizationAppKeyboardBacklightProvider
personalization_app::mojom::KeyboardBacklightProvider>
receiver) override;

void SetKeyboardBacklightObserver(
mojo::PendingRemote<
ash::personalization_app::mojom::KeyboardBacklightObserver> observer)
override {}

void SetBacklightColor(mojom::BacklightColor backlight_color) override {}

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ void PersonalizationAppKeyboardBacklightProviderImpl::BindInterface(
keyboard_backlight_receiver_.Bind(std::move(receiver));
}

void PersonalizationAppKeyboardBacklightProviderImpl::
SetKeyboardBacklightObserver(
mojo::PendingRemote<
ash::personalization_app::mojom::KeyboardBacklightObserver>
observer) {
// May already be bound if user refreshes page.
keyboard_backlight_observer_remote_.reset();
keyboard_backlight_observer_remote_.Bind(std::move(observer));

// Call it once to get the status of color preset.
NotifyBacklightColorChanged();
}

void PersonalizationAppKeyboardBacklightProviderImpl::SetBacklightColor(
mojom::BacklightColor backlight_color) {
if (!ash::features::IsRgbKeyboardEnabled()) {
Expand Down Expand Up @@ -72,6 +85,18 @@ void PersonalizationAppKeyboardBacklightProviderImpl::SetBacklightColor(
DCHECK(pref_service);
pref_service->SetInteger(ash::prefs::kPersonalizationKeyboardBacklightColor,
static_cast<int>(backlight_color));

NotifyBacklightColorChanged();
}

void PersonalizationAppKeyboardBacklightProviderImpl::
NotifyBacklightColorChanged() {
DCHECK(keyboard_backlight_observer_remote_.is_bound());
PrefService* pref_service = profile_->GetPrefs();
DCHECK(pref_service);
keyboard_backlight_observer_remote_->OnBacklightColorChanged(
static_cast<mojom::BacklightColor>(pref_service->GetInteger(
prefs::kPersonalizationKeyboardBacklightColor)));
}

} // namespace personalization_app
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,27 @@ class PersonalizationAppKeyboardBacklightProviderImpl
ash::personalization_app::mojom::KeyboardBacklightProvider>
receiver) override;

// mojom::PersonalizationAppKeyboardBacklightProvider:
void SetKeyboardBacklightObserver(
mojo::PendingRemote<
ash::personalization_app::mojom::KeyboardBacklightObserver> observer)
override;

void SetBacklightColor(
ash::personalization_app::mojom::BacklightColor backlight_color) override;

private:
// Notify webUI the current state of backlight color.
void NotifyBacklightColorChanged();

// Pointer to profile of user that opened personalization SWA. Not owned.
raw_ptr<Profile> const profile_ = nullptr;

mojo::Receiver<ash::personalization_app::mojom::KeyboardBacklightProvider>
keyboard_backlight_receiver_{this};

mojo::Remote<ash::personalization_app::mojom::KeyboardBacklightObserver>
keyboard_backlight_observer_remote_;
};

} // namespace ash::personalization_app
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,35 @@ namespace {

constexpr char kFakeTestEmail[] = "fakeemail@personalization";

class TestKeyboardBacklightObserver
: public ash::personalization_app::mojom::KeyboardBacklightObserver {
public:
void OnBacklightColorChanged(mojom::BacklightColor backlight_color) override {
backlight_color_ = backlight_color;
}

mojo::PendingRemote<
ash::personalization_app::mojom::KeyboardBacklightObserver>
pending_remote() {
if (keyboard_backlight_observer_receiver_.is_bound()) {
keyboard_backlight_observer_receiver_.reset();
}

return keyboard_backlight_observer_receiver_.BindNewPipeAndPassRemote();
}

mojom::BacklightColor backlight_color() {
keyboard_backlight_observer_receiver_.FlushForTesting();
return backlight_color_;
}

private:
mojo::Receiver<ash::personalization_app::mojom::KeyboardBacklightObserver>
keyboard_backlight_observer_receiver_{this};

mojom::BacklightColor backlight_color_ = mojom::BacklightColor::kWallpaper;
};

} // namespace

class PersonalizationAppKeyboardBacklightProviderImplTest
Expand Down Expand Up @@ -76,6 +105,16 @@ class PersonalizationAppKeyboardBacklightProviderImplTest
return keyboard_backlight_provider_.get();
}

void SetKeyboardBacklightObserver() {
keyboard_backlight_provider_remote_->SetKeyboardBacklightObserver(
test_keyboard_backlight_observer_.pending_remote());
}

mojom::BacklightColor ObservedBacklightColor() {
keyboard_backlight_provider_remote_.FlushForTesting();
return test_keyboard_backlight_observer_.backlight_color();
}

private:
base::test::ScopedFeatureList scoped_feature_list_;
user_manager::ScopedUserManager scoped_user_manager_;
Expand All @@ -87,17 +126,23 @@ class PersonalizationAppKeyboardBacklightProviderImplTest
keyboard_backlight_provider_remote_;
std::unique_ptr<PersonalizationAppKeyboardBacklightProviderImpl>
keyboard_backlight_provider_;
TestKeyboardBacklightObserver test_keyboard_backlight_observer_;
};

TEST_F(PersonalizationAppKeyboardBacklightProviderImplTest,
SetBackgroundColor) {
SetKeyboardBacklightObserver();
keyboard_backlight_provider_remote()->FlushForTesting();
keyboard_backlight_provider()->SetBacklightColor(
mojom::BacklightColor::kBlue);

// Verify the backlight color pref is saved.
EXPECT_EQ(profile()->GetPrefs()->GetInteger(
ash::prefs::kPersonalizationKeyboardBacklightColor),
static_cast<int>(mojom::BacklightColor::kBlue));

// Verify JS side is notified.
EXPECT_EQ(mojom::BacklightColor::kBlue, ObservedBacklightColor());
}

} // namespace personalization_app
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import 'chrome://personalization/strings.m.js';
import 'chrome://webui-test/mojo_webui_test_support.js';

import {KeyboardBacklight, KeyboardBacklightActionName, SetBacklightColorAction} from 'chrome://personalization/trusted/personalization_app.js';
import {KeyboardBacklight, KeyboardBacklightActionName, KeyboardBacklightObserver, SetBacklightColorAction} from 'chrome://personalization/trusted/personalization_app.js';
import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';

import {baseSetup, initElement, teardownElement} from './personalization_app_test_utils.js';
Expand All @@ -21,11 +21,13 @@ suite('KeyboardBacklightTest', function() {
const mocks = baseSetup();
keyboardBacklightProvider = mocks.keyboardBacklightProvider;
personalizationStore = mocks.personalizationStore;
KeyboardBacklightObserver.initKeyboardBacklightObserverIfNeeded();
});

teardown(async () => {
await teardownElement(keyboardBacklightElement);
keyboardBacklightElement = null;
KeyboardBacklightObserver.shutdown();
});


Expand Down Expand Up @@ -69,4 +71,33 @@ suite('KeyboardBacklightTest', function() {
assertTrue(!!action.backlightColor);
assertTrue(!!personalizationStore.data.keyboardBacklight.backlightColor);
});

test('sets backlight color in store on first load', async () => {
personalizationStore.expectAction(
KeyboardBacklightActionName.SET_BACKLIGHT_COLOR);
keyboardBacklightElement = initElement(KeyboardBacklight);
await keyboardBacklightProvider.whenCalled('setKeyboardBacklightObserver');
keyboardBacklightProvider.fireOnBacklightColorChanged(
keyboardBacklightProvider.backlightColor);
const action = await personalizationStore.waitForAction(
KeyboardBacklightActionName.SET_BACKLIGHT_COLOR) as
SetBacklightColorAction;
assertEquals(
keyboardBacklightProvider.backlightColor, action.backlightColor);
});

test('sets backlight color data in store on changed', async () => {
await keyboardBacklightProvider.whenCalled('setKeyboardBacklightObserver');

personalizationStore.expectAction(
KeyboardBacklightActionName.SET_BACKLIGHT_COLOR);
keyboardBacklightProvider.keyboardBacklightObserverRemote!
.onBacklightColorChanged(keyboardBacklightProvider.backlightColor);

const {backlightColor} =
await personalizationStore.waitForAction(
KeyboardBacklightActionName.SET_BACKLIGHT_COLOR) as
SetBacklightColorAction;
assertEquals(keyboardBacklightProvider.backlightColor, backlightColor);
});
});

0 comments on commit 97fdff7

Please sign in to comment.