Commit f248d40d authored by Evan Liu's avatar Evan Liu Committed by Commit Bot

Add UI to customization caption styling

Allow Chrome users on platform that do not have system caption
styling to provide a default styling for WebVTT captions displayed
by Blink. This should affect Chrome OS and Linux as Windows, macOS
and Android have system settings.

Design doc: https://docs.google.com/document/d/1wgKMbvP8nJkUKXkwnh5iEajSa4GHxDURL8kHIyHEO4s/edit?hl=en#

Bug: 976966
Change-Id: I41282753305b81f76e6b3f565516160cd63d69f9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1656714Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Reviewed-by: default avatarEsmael El-Moslimany <aee@chromium.org>
Commit-Queue: Evan Liu <evliu@google.com>
Cr-Commit-Position: refs/heads/master@{#672706}
parent cd7569ec
...@@ -162,6 +162,78 @@ ...@@ -162,6 +162,78 @@
</if> </if>
<!-- Accessibility Page --> <!-- Accessibility Page -->
<message name="IDS_SETTINGS_CAPTIONS" desc="Name of the settings page which displays caption preferences.">
Captions
</message>
<message name="IDS_SETTINGS_CAPTIONS_TEXT_SIZE" desc="Name of the settings page which displays caption text size preferences.">
Text size
</message>
<message name="IDS_SETTINGS_CAPTIONS_TEXT_FONT" desc="Name of the settings page which displays caption text font preferences.">
Text font
</message>
<message name="IDS_SETTINGS_CAPTIONS_TEXT_COLOR" desc="Name of the settings page which displays caption text color preferences.">
Text color
</message>
<message name="IDS_SETTINGS_CAPTIONS_TEXT_OPACITY" desc="Name of the settings page which displays caption text opacity preferences.">
Text opacity
</message>
<message name="IDS_SETTINGS_CAPTIONS_BACKGROUND_OPACITY" desc="Name of the settings page which displays caption background opacity preferences.">
Background opacity
</message>
<message name="IDS_SETTINGS_CAPTIONS_OPACITY_MIN" desc="Value of the minimum captions text opacity setting.">
0
</message>
<message name="IDS_SETTINGS_CAPTIONS_OPACITY_MAX" desc="Value of the maximum captions text opacity setting.">
100
</message>
<message name="IDS_SETTINGS_CAPTIONS_TEXT_SHADOW" desc="Name of the settings page which displays caption text shadow preferences.">
Text shadow
</message>
<message name="IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_NONE" desc="Name of the None option for the caption text shadow.">
None
</message>
<message name="IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_RAISED" desc="Name of the Raised option for the caption text shadow.">
Raised
</message>
<message name="IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_DEPRESSED" desc="Name of the Depressed option for the caption text shadow.">
Depressed
</message>
<message name="IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_UNIFORM" desc="Name of the Uniform option for the caption text shadow.">
Uniform
</message>
<message name="IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_DROP_SHADOW" desc="Name of the Drop shadow option for the caption text shadow.">
Drop shadow
</message>
<message name="IDS_SETTINGS_CAPTIONS_BACKGROUND_COLOR" desc="Name of the settings page which displays caption background color preferences.">
Background color
</message>
<message name="IDS_SETTINGS_CAPTIONS_COLOR_BLACK" desc="Name of the Black color for the caption text or background.">
Black
</message>
<message name="IDS_SETTINGS_CAPTIONS_COLOR_WHITE" desc="Name of the White color for the caption text or background.">
White
</message>
<message name="IDS_SETTINGS_CAPTIONS_COLOR_RED" desc="Name of the Red color for the caption text or background.">
Red
</message>
<message name="IDS_SETTINGS_CAPTIONS_COLOR_GREEN" desc="Name of the Green color for the caption text or background.">
Green
</message>
<message name="IDS_SETTINGS_CAPTIONS_COLOR_BLUE" desc="Name of the Blue color for the caption text or background.">
Blue
</message>
<message name="IDS_SETTINGS_CAPTIONS_COLOR_YELLOW" desc="Name of the Yellow color for the caption text or background.">
Yellow
</message>
<message name="IDS_SETTINGS_CAPTIONS_COLOR_CYAN" desc="Name of the Cyan color for the caption text or background.">
Cyan
</message>
<message name="IDS_SETTINGS_CAPTIONS_COLOR_MAGENTA" desc="Name of the Magenta color for the caption text or background.">
Magenta
</message>
<message name="IDS_SETTINGS_CAPTIONS_DEFAULT_SETTING" desc="Name of the default setting for the caption text.">
Default
</message>
<message name="IDS_SETTINGS_ACCESSIBILITY" desc="Name of the settings page which displays accessibility preferences."> <message name="IDS_SETTINGS_ACCESSIBILITY" desc="Name of the settings page which displays accessibility preferences.">
Accessibility Accessibility
</message> </message>
......
3e05aa8562cd7a68d00d313431aca4dfe7effc5e
\ No newline at end of file
...@@ -3840,6 +3840,20 @@ jumbo_split_static_library("browser") { ...@@ -3840,6 +3840,20 @@ jumbo_split_static_library("browser") {
] ]
} }
if (is_mac) {
sources += [
"accessibility/caption_settings_dialog.h",
"accessibility/caption_settings_dialog_mac.mm",
]
}
if (is_win) {
sources += [
"accessibility/caption_settings_dialog.h",
"accessibility/caption_settings_dialog_win.cc",
]
}
if (is_win || is_mac || is_desktop_linux) { if (is_win || is_mac || is_desktop_linux) {
sources += [ sources += [
"browser_switcher/alternative_browser_driver.h", "browser_switcher/alternative_browser_driver.h",
......
// 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.
#ifndef CHROME_BROWSER_ACCESSIBILITY_CAPTION_SETTINGS_DIALOG_H_
#define CHROME_BROWSER_ACCESSIBILITY_CAPTION_SETTINGS_DIALOG_H_
#include "base/macros.h"
namespace captions {
// An abstraction of a caption settings dialog. This is used for the captions
// sub-section of Settings.
class CaptionSettingsDialog {
public:
// Displays the native captions manager dialog.
static void ShowCaptionSettingsDialog();
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(CaptionSettingsDialog);
};
} // namespace captions
#endif // CHROME_BROWSER_ACCESSIBILITY_CAPTION_SETTINGS_DIALOG_H_
// 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/accessibility/caption_settings_dialog.h"
#import <AppKit/AppKit.h>
namespace captions {
static NSString* kCaptionSettingsUrlString =
@"x-apple.systempreferences:com.apple.preference.universalaccess?"
@"Captioning";
void CaptionSettingsDialog::ShowCaptionSettingsDialog() {
[[NSWorkspace sharedWorkspace]
openURL:[NSURL URLWithString:kCaptionSettingsUrlString]];
}
} // namespace captions
// 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/accessibility/caption_settings_dialog.h"
#include <windows.h>
#include <shellapi.h>
#include "base/bind.h"
#include "base/task/post_task.h"
#include "base/win/windows_version.h"
namespace {
// A helper callback that opens the caption settings dialog.
void CaptionSettingsDialogCallback() {
if (base::win::GetVersion() >= base::win::Version::WIN10) {
ShellExecute(NULL, L"open", L"ms-settings:easeofaccess-closedcaptioning",
NULL, NULL, SW_SHOWNORMAL);
}
}
} // namespace
namespace captions {
void CaptionSettingsDialog::ShowCaptionSettingsDialog() {
base::PostTaskWithTraits(
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
base::BindOnce(CaptionSettingsDialogCallback));
}
} // namespace captions
...@@ -3154,19 +3154,25 @@ base::Optional<ui::CaptionStyle> GetCaptionStyleFromPrefs(PrefService* prefs) { ...@@ -3154,19 +3154,25 @@ base::Optional<ui::CaptionStyle> GetCaptionStyleFromPrefs(PrefService* prefs) {
style.text_size = prefs->GetString(prefs::kAccessibilityCaptionsTextSize); style.text_size = prefs->GetString(prefs::kAccessibilityCaptionsTextSize);
style.font_family = prefs->GetString(prefs::kAccessibilityCaptionsTextFont); style.font_family = prefs->GetString(prefs::kAccessibilityCaptionsTextFont);
style.text_color = base::StringPrintf( if (!prefs->GetString(prefs::kAccessibilityCaptionsTextColor).empty()) {
"rgba(%s,%s)", style.text_color = base::StringPrintf(
prefs->GetString(prefs::kAccessibilityCaptionsTextColor).c_str(), "rgba(%s,%s)",
base::NumberToString( prefs->GetString(prefs::kAccessibilityCaptionsTextColor).c_str(),
prefs->GetInteger(prefs::kAccessibilityCaptionsTextOpacity) / 100.0) base::NumberToString(
.c_str()); prefs->GetInteger(prefs::kAccessibilityCaptionsTextOpacity) / 100.0)
style.background_color = base::StringPrintf( .c_str());
"rgba(%s,%s)", }
prefs->GetString(prefs::kAccessibilityCaptionsBackgroundColor).c_str(),
base::NumberToString( if (!prefs->GetString(prefs::kAccessibilityCaptionsBackgroundColor).empty()) {
prefs->GetInteger(prefs::kAccessibilityCaptionsBackgroundOpacity) / style.background_color = base::StringPrintf(
100.0) "rgba(%s,%s)",
.c_str()); prefs->GetString(prefs::kAccessibilityCaptionsBackgroundColor).c_str(),
base::NumberToString(
prefs->GetInteger(prefs::kAccessibilityCaptionsBackgroundOpacity) /
100.0)
.c_str());
}
style.text_shadow = prefs->GetString(prefs::kAccessibilityCaptionsTextShadow); style.text_shadow = prefs->GetString(prefs::kAccessibilityCaptionsTextShadow);
return style; return style;
......
...@@ -7,6 +7,8 @@ import("//third_party/closure_compiler/compile_js.gni") ...@@ -7,6 +7,8 @@ import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") { js_type_check("closure_compile") {
deps = [ deps = [
":a11y_page", ":a11y_page",
":captions_browser_proxy",
":captions_subpage",
] ]
if (is_chromeos) { if (is_chromeos) {
...@@ -19,6 +21,16 @@ js_type_check("closure_compile") { ...@@ -19,6 +21,16 @@ js_type_check("closure_compile") {
} }
} }
js_library("captions_subpage") {
deps = [
"../appearance_page:fonts_browser_proxy",
"../controls:settings_dropdown_menu",
"//ui/webui/resources/cr_elements/cr_slider:cr_slider",
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
js_library("a11y_page") { js_library("a11y_page") {
deps = [ deps = [
"..:route", "..:route",
...@@ -61,3 +73,9 @@ js_library("tts_subpage") { ...@@ -61,3 +73,9 @@ js_library("tts_subpage") {
js_library("externs") { js_library("externs") {
} }
js_library("captions_browser_proxy") {
deps = [
"//ui/webui/resources/js:cr",
]
}
<link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="captions_browser_proxy.html">
<link rel="import" href="captions_subpage.html">
<link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html"> <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="../i18n_setup.html"> <link rel="import" href="../i18n_setup.html">
...@@ -17,76 +19,100 @@ ...@@ -17,76 +19,100 @@
<dom-module id="settings-a11y-page"> <dom-module id="settings-a11y-page">
<template> <template>
<style include="settings-shared"></style> <style include="settings-shared"></style>
<if expr="chromeos"> <settings-animated-pages id="pages" current-route="{{currentRoute}}"
<template is="dom-if" if="[[pageVisibility.webstoreLink]]"> section="a11y" focus-config="[[focusConfig_]]">
<settings-animated-pages id="pages" current-route="{{currentRoute}}" <if expr="not chromeos">
section="a11y" focus-config="[[focusConfig_]]">
<div route-path="default"> <div route-path="default">
<settings-toggle-button <template is="dom-if" if="[[showCaptionSettings_]]">
id="a11yImageLabels" <cr-link-row class="hr" id="captions" label="$i18n{captionsTitle}"
hidden$="[[!showAccessibilityLabelsSetting_]]" on-click="onTapCaptions_">
pref="{{prefs.settings.a11y.enable_accessibility_image_labels}}" </cr-link-row>
on-change="onToggleAccessibilityImageLabels_" </template>
label="$i18n{accessibleImageLabelsTitle}" <if expr="not chromeos">
sub-label="$i18n{accessibleImageLabelsSubtitle}"> <settings-toggle-button id="a11yImageLabels"
</settings-toggle-button> hidden$="[[!showAccessibilityLabelsSetting_]]"
<settings-toggle-button id="optionsInMenuToggle" pref="{{prefs.settings.a11y.enable_accessibility_image_labels}}"
label="$i18n{optionsInMenuLabel}" on-change="onToggleAccessibilityImageLabels_"
pref="{{prefs.settings.a11y.enable_menu}}"> label="$i18n{accessibleImageLabelsTitle}"
</settings-toggle-button> sub-label="$i18n{accessibleImageLabelsSubtitle}">
<cr-link-row class="hr" id="subpage-trigger" </settings-toggle-button>
label="$i18n{manageAccessibilityFeatures}" <cr-link-row class="hr" label="$i18n{moreFeaturesLink}"
on-click="onManageAccessibilityFeaturesTap_" on-click="onMoreFeaturesLinkClick_"
sub-label="$i18n{moreFeaturesLinkDescription}"> sub-label="$i18n{a11yWebStore}" external></cr-link-row>
</cr-link-row> </if>
</div> </div>
</if>
<template is="dom-if" route-path="/manageAccessibility"> <if expr="chromeos">
<settings-subpage <template is="dom-if" if="[[pageVisibility.webstoreLink]]">
associated-control="[[$$('#subpage-trigger')]]" <div route-path="default">
page-title="$i18n{manageAccessibilityFeatures}"> <template is="dom-if" if="[[showCaptionSettings_]]">
<settings-manage-a11y-page prefs="{{prefs}}"> <cr-link-row class="hr" id="captions"
</settings-manage-a11y-page> label="$i18n{captionsTitle}"
</settings-subpage> on-click="onTapCaptions_">
</template> </cr-link-row>
<template is="dom-if" route-path="/manageAccessibility/tts"> </template>
<settings-subpage <settings-toggle-button id="a11yImageLabels"
associated-control="[[$$('#subpage-trigger')]]" hidden$="[[!showAccessibilityLabelsSetting_]]"
page-title="$i18n{manageTtsSettings}"> pref="{{prefs.settings.a11y.enable_accessibility_image_labels}}"
<settings-tts-subpage prefs="{{prefs}}"> on-change="onToggleAccessibilityImageLabels_"
</settings-tts-subpage> label="$i18n{accessibleImageLabelsTitle}"
</settings-subpage> sub-label="$i18n{accessibleImageLabelsSubtitle}">
</template> </settings-toggle-button>
<template is="dom-if" if="[[showExperimentalSwitchAccess_]]"> <settings-toggle-button id="optionsInMenuToggle"
<template is="dom-if" route-path="/manageAccessibility/switchAccess"> label="$i18n{optionsInMenuLabel}"
pref="{{prefs.settings.a11y.enable_menu}}">
</settings-toggle-button>
<cr-link-row class="hr" id="subpage-trigger"
label="$i18n{manageAccessibilityFeatures}"
on-click="onManageAccessibilityFeaturesTap_"
sub-label="$i18n{moreFeaturesLinkDescription}">
</cr-link-row>
</div>
<template is="dom-if" route-path="/manageAccessibility">
<settings-subpage associated-control="[[$$('#subpage-trigger')]]" <settings-subpage associated-control="[[$$('#subpage-trigger')]]"
page-title="$i18n{manageSwitchAccessSettings}"> page-title="$i18n{manageAccessibilityFeatures}">
<settings-switch-access-subpage prefs="{{prefs.settings.a11y}}"> <settings-manage-a11y-page prefs="{{prefs}}">
</settings-switch-access-subpage> </settings-manage-a11y-page>
</settings-subpage>
</template>
<template is="dom-if" route-path="/manageAccessibility/tts">
<settings-subpage
associated-control="[[$$('#subpage-trigger')]]"
page-title="$i18n{manageTtsSettings}">
<settings-tts-subpage prefs="{{prefs}}">
</settings-tts-subpage>
</settings-subpage> </settings-subpage>
</template> </template>
<template is="dom-if" if="[[showExperimentalSwitchAccess_]]">
<template is="dom-if"
route-path="/manageAccessibility/switchAccess">
<settings-subpage associated-control="[[$$('#subpage-trigger')]]"
page-title="$i18n{manageSwitchAccessSettings}">
<settings-switch-access-subpage prefs="{{prefs.settings.a11y}}">
</settings-switch-access-subpage>
</settings-subpage>
</template>
</template>
</template> </template>
</settings-animated-pages> <cr-link-row class="hr"
</template> label="$i18n{moreFeaturesLink}"
<cr-link-row class="hr" label="$i18n{moreFeaturesLink}" on-click="onMoreFeaturesLinkClick_"
on-click="onMoreFeaturesLinkClick_" sub-label="$i18n{a11yWebStore}" sub-label="$i18n{a11yWebStore}"
hidden="[[pageVisibility.webstoreLink]]" hidden="[[pageVisibility.webstoreLink]]" external></cr-link-row>
external></cr-link-row> </if>
</if>
<if expr="not chromeos"> <if expr="chromeos or is_linux or is_win">
<settings-toggle-button <template is="dom-if" if="[[showCaptionSettings_]]">
id="a11yImageLabels" <template is="dom-if" route-path="/captions">
hidden$="[[!showAccessibilityLabelsSetting_]]" <settings-subpage
pref="{{prefs.settings.a11y.enable_accessibility_image_labels}}" associated-control="[[$$('#captions')]]"
on-change="onToggleAccessibilityImageLabels_" page-title="$i18n{captionsTitle}">
label="$i18n{accessibleImageLabelsTitle}" <settings-captions prefs="{{prefs}}"></settings-captions>
sub-label="$i18n{accessibleImageLabelsSubtitle}"> </settings-subpage>
</settings-toggle-button> </template>
<cr-link-row class="hr" label="$i18n{moreFeaturesLink}" </template>
on-click="onMoreFeaturesLinkClick_" sub-label="$i18n{a11yWebStore}" </if>
external></cr-link-row> </settings-animated-pages>
</if>
</template> </template>
<script src="a11y_page.js"></script> <script src="a11y_page.js"></script>
......
...@@ -43,6 +43,9 @@ Polymer({ ...@@ -43,6 +43,9 @@ Polymer({
type: Object, type: Object,
value: function() { value: function() {
const map = new Map(); const map = new Map();
if (settings.routes.CAPTIONS) {
map.set(settings.routes.CAPTIONS.path, '#captions');
}
// <if expr="chromeos"> // <if expr="chromeos">
if (settings.routes.MANAGE_ACCESSIBILITY) { if (settings.routes.MANAGE_ACCESSIBILITY) {
map.set( map.set(
...@@ -53,6 +56,17 @@ Polymer({ ...@@ -53,6 +56,17 @@ Polymer({
}, },
}, },
/**
* Whether to show the link to caption settings.
* @private {boolean}
*/
showCaptionSettings_: {
type: Boolean,
value: function() {
return loadTimeData.getBoolean('enableCaptionSettings');
},
},
// <if expr="chromeos"> // <if expr="chromeos">
/** /**
* Whether to show experimental accessibility features. * Whether to show experimental accessibility features.
...@@ -121,4 +135,29 @@ Polymer({ ...@@ -121,4 +135,29 @@ Polymer({
window.open( window.open(
'https://chrome.google.com/webstore/category/collection/accessibility'); 'https://chrome.google.com/webstore/category/collection/accessibility');
}, },
/** @private */
onTapCaptions_: function() {
// Open the system captions dialog for Mac.
// <if expr="is_macosx">
settings.CaptionsBrowserProxyImpl.getInstance().openSystemCaptionsDialog();
// </if>
// Open the system captions dialog for Windows 10+ or navigate to the
// caption settings page for older versions of Windows
// <if expr="is_win">
if (loadTimeData.getBoolean('isWindows10OrNewer')) {
settings.CaptionsBrowserProxyImpl.getInstance()
.openSystemCaptionsDialog();
} else {
settings.navigateTo(settings.routes.CAPTIONS);
}
// </if>
// Navigate to the caption settings page for ChromeOS and Linux as they
// do not have system caption settings.
// <if expr="chromeos or is_linux">
settings.navigateTo(settings.routes.CAPTIONS);
// </if>
},
}); });
<link rel="import" href="chrome://resources/html/cr.html">
<script src="captions_browser_proxy.js"></script>
// 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.
/**
* @fileoverview A helper object used from the Chrome captions section to
* interact with the browser. Used on operating system that is not Chrome OS.
*/
cr.define('settings', function() {
/** @interface */
class CaptionsBrowserProxy {
/**
* Open the native captions system dialog.
*/
openSystemCaptionsDialog() {}
}
/**
* @implements {settings.CaptionsBrowserProxy}
*/
class CaptionsBrowserProxyImpl {
/** @override */
openSystemCaptionsDialog() {
chrome.send('openSystemCaptionsDialog');
}
}
cr.addSingletonGetter(CaptionsBrowserProxyImpl);
return {
CaptionsBrowserProxy: CaptionsBrowserProxy,
CaptionsBrowserProxyImpl: CaptionsBrowserProxyImpl,
};
});
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="../appearance_page/fonts_browser_proxy.html">
<link rel="import" href="../controls/settings_dropdown_menu.html">
<link rel="import" href="../controls/settings_slider.html">
<link rel="import" href="../settings_shared_css.html">
<dom-module id="settings-captions">
<template>
<style include="settings-shared"></style>
<div class="settings-box">
<div class="start">$i18n{captionsTextSize}</div>
<settings-dropdown-menu id="captionsTextSize"
label="$i18n{captionsTextSize}"
pref="{{prefs.accessibility.captions.text_size}}"
menu-options="[[textSizeOptions_]]">
</settings-dropdown-menu>
</div>
<div class="settings-box">
<div class="start">$i18n{captionsTextFont}</div>
<settings-dropdown-menu id="captionsTextFont"
label="$i18n{captionsTextFont}"
pref="{{prefs.accessibility.captions.text_font}}"
menu-options="[[textFontOptions_]]">
</settings-dropdown-menu>
</div>
<div class="settings-box">
<div class="start">$i18n{captionsTextColor}</div>
<settings-dropdown-menu id="captionsTextColor"
label="$i18n{captionsTextColor}"
pref="{{prefs.accessibility.captions.text_color}}"
menu-options="[[colorOptions_]]">
</settings-dropdown-menu>
</div>
<div class="settings-box">
<div class="start">$i18n{captionsTextOpacity}</div>
<settings-slider id="captionsTextOpacity"
ticks="[[textOpacityRange_]]"
label-min="$i18n{captionsOpacityMin}"
label-max="$i18n{captionsOpacityMax}"
pref="{{prefs.accessibility.captions.text_opacity}}">
</settings-slider>
</div>
<div class="settings-box">
<div class="start">$i18n{captionsTextShadow}</div>
<settings-dropdown-menu id="captionsTextShadow"
label="$i18n{captionsTextShadow}"
pref="{{prefs.accessibility.captions.text_shadow}}"
menu-options="[[textShadowOptions_]]">
</settings-dropdown-menu>
</div>
<div class="settings-box">
<div class="start">$i18n{captionsBackgroundColor}</div>
<settings-dropdown-menu id="captionsBackgroundColor"
label="$i18n{captionsBackgroundColor}"
pref="{{prefs.accessibility.captions.background_color}}"
menu-options="[[colorOptions_]]">
</settings-dropdown-menu>
</div>
<div class="settings-box">
<div class="start">$i18n{captionsBackgroundOpacity}</div>
<settings-slider id="captionsBackgroundOpacity"
ticks="[[textOpacityRange_]]"
label-min="$i18n{captionsOpacityMin}"
label-max="$i18n{captionsOpacityMax}"
pref="{{prefs.accessibility.captions.background_opacity}}">
</settings-slider>
</div>
<div class="list-frame">
<div class="list-item">
<span style="
font-size:[[prefs.accessibility.captions.text_size.value]];
font-family:[[prefs.accessibility.captions.text_font.value]];
background-color: [[computeBackgroundColor_(
prefs.accessibility.captions.background_opacity.value,
prefs.accessibility.captions.background_color.value)]];
color: [[computeTextColor_(
prefs.accessibility.captions.text_opacity.value,
prefs.accessibility.captions.text_color.value)]];
text-shadow: [[prefs.accessibility.captions.text_shadow.value]];
padding: [[computePadding_(
prefs.accessibility.captions.text_size.value)]]">
$i18n{quickBrownFox}
</span>
</div>
</div>
</template>
<script src="captions_subpage.js"></script>
</dom-module>
// 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.
/**
* @fileoverview 'settings-captions' is a component for showing captions
* settings subpage (chrome://settings/captions).
*/
(function() {
'use strict';
/** @type {!Array<number>} */
const TEXT_OPACITY_RANGE = [
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50,
55, 60, 65, 70, 75, 80, 85, 90, 95, 100
];
/**
* @param {!Array<number>} ticks
* @return {!Array<!cr_slider.SliderTick>}
*/
function ticksWithLabels(ticks) {
return ticks.map(x => ({label: `${x}`, value: x}));
}
Polymer({
is: 'settings-captions',
behaviors: [I18nBehavior, WebUIListenerBehavior],
properties: {
prefs: {
type: Object,
notify: true,
},
/**
* List of fonts populated by the fonts browser proxy.
* @private {!DropdownMenuOptionList} */
textFontOptions_: Object,
/**
* Reasonable, text opacity range.
* @private {!Array<!cr_slider.SliderTick>}
*/
textOpacityRange_: {
readOnly: true,
type: Array,
value: ticksWithLabels(TEXT_OPACITY_RANGE),
},
/**
* List of options for the text size drop-down menu.
* @type {!DropdownMenuOptionList}
*/
textSizeOptions_: {
readOnly: true,
type: Array,
value: function() {
return [
{value: '50%', name: loadTimeData.getString('verySmall')},
{value: '75%', name: loadTimeData.getString('small')},
{value: '', name: loadTimeData.getString('medium')}, // Default = 100%
{value: '150%', name: loadTimeData.getString('large')},
{value: '200%', name: loadTimeData.getString('veryLarge')},
];
},
},
/**
* List of options for the color drop-down menu.
* @type {!DropdownMenuOptionList}
*/
colorOptions_: {
readOnly: true,
type: Array,
value: function() {
return [
{value: '', name: loadTimeData.getString('captionsDefaultSetting')},
{value: '0,0,0', name: loadTimeData.getString('captionsColorBlack')},
{
value: '255,255,255',
name: loadTimeData.getString('captionsColorWhite')
},
{value: '255,0,0', name: loadTimeData.getString('captionsColorRed')},
{
value: '0,255,0',
name: loadTimeData.getString('captionsColorGreen')
},
{value: '0,0,255', name: loadTimeData.getString('captionsColorBlue')},
{
value: '255,255,0',
name: loadTimeData.getString('captionsColorYellow')
},
{
value: '0,255,255',
name: loadTimeData.getString('captionsColorCyan')
},
{
value: '255,0,255',
name: loadTimeData.getString('captionsColorMagenta')
},
];
},
},
/**
* List of options for the text shadow drop-down menu.
* @type {!DropdownMenuOptionList}
*/
textShadowOptions_: {
readOnly: true,
type: Array,
value: function() {
return [
{value: '', name: loadTimeData.getString('captionsTextShadowNone')},
{
value: '-2px -2px 4px rgba(0, 0, 0, 0.5)',
name: loadTimeData.getString('captionsTextShadowRaised')
},
{
value: '2px 2px 4px rgba(0, 0, 0, 0.5)',
name: loadTimeData.getString('captionsTextShadowDepressed')
},
{
value: '-1px 0px 0px black, ' +
'0px -1px 0px black, 1px 0px 0px black, 0px 1px 0px black',
name: loadTimeData.getString('captionsTextShadowUniform')
},
{
value: '0px 0px 2px rgba(0, 0, 0, 0.5), 2px 2px 2px black',
name: loadTimeData.getString('captionsTextShadowDropShadow')
},
];
},
},
},
/** @private {?settings.FontsBrowserProxy} */
browserProxy_: null,
/** @override */
created: function() {
this.browserProxy_ = settings.FontsBrowserProxyImpl.getInstance();
},
/** @override */
ready: function() {
this.browserProxy_.observeAdvancedFontExtensionAvailable();
this.browserProxy_.fetchFontsData().then(this.setFontsData_.bind(this));
},
/**
* @param {!FontsData} response A list of fonts.
* @private
*/
setFontsData_: function(response) {
const fontMenuOptions =
[{value: '', name: loadTimeData.getString('captionsDefaultSetting')}];
for (const fontData of response.fontList) {
fontMenuOptions.push({value: fontData[0], name: fontData[1]});
}
this.textFontOptions_ = fontMenuOptions;
},
/**
* Get the background color as a RGBA string.
* @return {string}
* @private
*/
computeBackgroundColor_: function() {
return this.formatRGAString_(
'prefs.accessibility.captions.background_color.value',
'prefs.accessibility.captions.background_opacity.value');
},
/**
* Get the text color as a RGBA string.
* @return {string}
* @private
*/
computeTextColor_: function() {
return this.formatRGAString_(
'prefs.accessibility.captions.text_color.value',
'prefs.accessibility.captions.text_opacity.value');
},
/**
* Formats the color as an RGBA string.
* @param {string} colorPreference The name of the preference containing the
* RGB values as a comma-separated string.
* @param {string} opacityPreference The name of the preference containing
* the opacity value as a percentage.
* @return {string} The formatted RGBA string.
* @private
*/
formatRGAString_: function(colorPreference, opacityPreference) {
return 'rgba(' + this.get(colorPreference) + ',' +
parseInt(this.get(opacityPreference), 10) / 100.0 + ')';
},
/**
* @param {string} size The font size of the captions text as a percentage.
* @return {string} The padding around the captions text as a percentage.
* @private
*/
computePadding_: function(size) {
if (size == '') {
return '1%';
}
return `${+size.slice(0, -1) / 100}%`;
}
});
})();
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
* BASIC: (undefined|!settings.Route), * BASIC: (undefined|!settings.Route),
* BLUETOOTH: (undefined|!settings.Route), * BLUETOOTH: (undefined|!settings.Route),
* BLUETOOTH_DEVICES: (undefined|!settings.Route), * BLUETOOTH_DEVICES: (undefined|!settings.Route),
* CAPTIONS: (undefined|!settings.Route),
* CERTIFICATES: (undefined|!settings.Route), * CERTIFICATES: (undefined|!settings.Route),
* CHANGE_PICTURE: (undefined|!settings.Route), * CHANGE_PICTURE: (undefined|!settings.Route),
* CHROME_CLEANUP: (undefined|!settings.Route), * CHROME_CLEANUP: (undefined|!settings.Route),
...@@ -463,6 +464,20 @@ cr.define('settings', function() { ...@@ -463,6 +464,20 @@ cr.define('settings', function() {
// </if> // </if>
r.ACCESSIBILITY = r.ADVANCED.createSection('/accessibility', 'a11y'); r.ACCESSIBILITY = r.ADVANCED.createSection('/accessibility', 'a11y');
// <if expr="chromeos or is_linux">
if (loadTimeData.getBoolean('enableCaptionSettings')) {
r.CAPTIONS = r.ACCESSIBILITY.createChild('/captions');
}
// </if>
// <if expr="is_win">
if (loadTimeData.getBoolean('enableCaptionSettings') &&
!loadTimeData.getBoolean('isWindows10OrNewer')) {
r.CAPTIONS = r.ACCESSIBILITY.createChild('/captions');
}
// </if>
// <if expr="chromeos"> // <if expr="chromeos">
r.MANAGE_ACCESSIBILITY = r.MANAGE_ACCESSIBILITY =
r.ACCESSIBILITY.createChild('/manageAccessibility'); r.ACCESSIBILITY.createChild('/manageAccessibility');
......
...@@ -21,6 +21,18 @@ ...@@ -21,6 +21,18 @@
type="chrome_html" type="chrome_html"
preprocess="true" preprocess="true"
allowexternalscript="true" /> allowexternalscript="true" />
<structure name="IDR_SETTINGS_CAPTIONS_SUBPAGE_HTML"
file="a11y_page/captions_subpage.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_CAPTIONS_SUBPAGE_JS"
file="a11y_page/captions_subpage.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_CAPTIONS_BROWSER_PROXY_HTML"
file="a11y_page/captions_browser_proxy.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_CAPTIONS_BROWSER_PROXY_JS"
file="a11y_page/captions_browser_proxy.js"
type="chrome_html" />
<if expr="chromeos"> <if expr="chromeos">
<structure name="IDR_SETTINGS_MANAGE_A11Y_PAGE_JS" <structure name="IDR_SETTINGS_MANAGE_A11Y_PAGE_JS"
file="a11y_page/manage_a11y_page.js" file="a11y_page/manage_a11y_page.js"
......
...@@ -335,6 +335,13 @@ jumbo_split_static_library("ui") { ...@@ -335,6 +335,13 @@ jumbo_split_static_library("ui") {
"webui/webui_util.h", "webui/webui_util.h",
] ]
if (is_win || is_mac) {
sources += [
"webui/settings/captions_handler.cc",
"webui/settings/captions_handler.h",
]
}
if (enable_vr) { if (enable_vr) {
if (is_win) { if (is_win) {
sources += [ sources += [
......
...@@ -30,6 +30,13 @@ const char* const kWebPrefsToObserve[] = { ...@@ -30,6 +30,13 @@ const char* const kWebPrefsToObserve[] = {
prefs::kWebKitDefaultFixedFontSize, prefs::kWebKitDefaultFixedFontSize,
prefs::kWebKitDefaultFontSize, prefs::kWebKitDefaultFontSize,
prefs::kWebKitDomPasteEnabled, prefs::kWebKitDomPasteEnabled,
prefs::kAccessibilityCaptionsTextSize,
prefs::kAccessibilityCaptionsTextFont,
prefs::kAccessibilityCaptionsTextColor,
prefs::kAccessibilityCaptionsTextOpacity,
prefs::kAccessibilityCaptionsBackgroundColor,
prefs::kAccessibilityCaptionsTextShadow,
prefs::kAccessibilityCaptionsBackgroundOpacity,
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
prefs::kWebKitFontScaleFactor, prefs::kWebKitFontScaleFactor,
prefs::kWebKitForceDarkModeEnabled, prefs::kWebKitForceDarkModeEnabled,
......
// 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/ui/webui/settings/captions_handler.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "chrome/browser/accessibility/caption_settings_dialog.h"
#include "content/public/browser/web_ui.h"
namespace settings {
CaptionsHandler::CaptionsHandler() {}
CaptionsHandler::~CaptionsHandler() {}
void CaptionsHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
"openSystemCaptionsDialog",
base::BindRepeating(&CaptionsHandler::HandleOpenSystemCaptionsDialog,
base::Unretained(this)));
}
void CaptionsHandler::OnJavascriptAllowed() {}
void CaptionsHandler::OnJavascriptDisallowed() {}
void CaptionsHandler::HandleOpenSystemCaptionsDialog(
const base::ListValue* args) {
captions::CaptionSettingsDialog::ShowCaptionSettingsDialog();
}
} // namespace settings
// 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.
#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CAPTIONS_HANDLER_H_
#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CAPTIONS_HANDLER_H_
#include "base/macros.h"
#include "build/build_config.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
namespace settings {
// UI handler for Chrome caption settings subpage on operating systems other
// than Chrome OS and Linux.
class CaptionsHandler : public SettingsPageUIHandler {
public:
CaptionsHandler();
~CaptionsHandler() override;
// SettingsPageUIHandler overrides:
void RegisterMessages() override;
void OnJavascriptAllowed() override;
void OnJavascriptDisallowed() override;
private:
void HandleOpenSystemCaptionsDialog(const base::ListValue* args);
DISALLOW_COPY_AND_ASSIGN(CaptionsHandler);
};
} // namespace settings
#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CAPTIONS_HANDLER_H_
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/win/windows_version.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "build/buildflag.h" #include "build/buildflag.h"
#include "chrome/browser/autofill/personal_data_manager_factory.h" #include "chrome/browser/autofill/personal_data_manager_factory.h"
...@@ -191,6 +192,32 @@ void AddA11yStrings(content::WebUIDataSource* html_source) { ...@@ -191,6 +192,32 @@ void AddA11yStrings(content::WebUIDataSource* html_source) {
{"moreFeaturesLink", IDS_SETTINGS_MORE_FEATURES_LINK}, {"moreFeaturesLink", IDS_SETTINGS_MORE_FEATURES_LINK},
{"moreFeaturesLinkDescription", {"moreFeaturesLinkDescription",
IDS_SETTINGS_MORE_FEATURES_LINK_DESCRIPTION}, IDS_SETTINGS_MORE_FEATURES_LINK_DESCRIPTION},
{"captionsTitle", IDS_SETTINGS_CAPTIONS},
{"captionsTextSize", IDS_SETTINGS_CAPTIONS_TEXT_SIZE},
{"captionsTextFont", IDS_SETTINGS_CAPTIONS_TEXT_FONT},
{"captionsTextColor", IDS_SETTINGS_CAPTIONS_TEXT_COLOR},
{"captionsTextOpacity", IDS_SETTINGS_CAPTIONS_TEXT_OPACITY},
{"captionsBackgroundOpacity", IDS_SETTINGS_CAPTIONS_BACKGROUND_OPACITY},
{"captionsOpacityMin", IDS_SETTINGS_CAPTIONS_OPACITY_MIN},
{"captionsOpacityMax", IDS_SETTINGS_CAPTIONS_OPACITY_MAX},
{"captionsTextShadow", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW},
{"captionsTextShadowNone", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_NONE},
{"captionsTextShadowRaised", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_RAISED},
{"captionsTextShadowDepressed",
IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_DEPRESSED},
{"captionsTextShadowUniform", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_UNIFORM},
{"captionsTextShadowDropShadow",
IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_DROP_SHADOW},
{"captionsBackgroundColor", IDS_SETTINGS_CAPTIONS_BACKGROUND_COLOR},
{"captionsColorBlack", IDS_SETTINGS_CAPTIONS_COLOR_BLACK},
{"captionsColorWhite", IDS_SETTINGS_CAPTIONS_COLOR_WHITE},
{"captionsColorRed", IDS_SETTINGS_CAPTIONS_COLOR_RED},
{"captionsColorGreen", IDS_SETTINGS_CAPTIONS_COLOR_GREEN},
{"captionsColorBlue", IDS_SETTINGS_CAPTIONS_COLOR_BLUE},
{"captionsColorYellow", IDS_SETTINGS_CAPTIONS_COLOR_YELLOW},
{"captionsColorCyan", IDS_SETTINGS_CAPTIONS_COLOR_CYAN},
{"captionsColorMagenta", IDS_SETTINGS_CAPTIONS_COLOR_MAGENTA},
{"captionsDefaultSetting", IDS_SETTINGS_CAPTIONS_DEFAULT_SETTING},
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
{"optionsInMenuLabel", IDS_SETTINGS_OPTIONS_IN_MENU_LABEL}, {"optionsInMenuLabel", IDS_SETTINGS_OPTIONS_IN_MENU_LABEL},
{"largeMouseCursorLabel", IDS_SETTINGS_LARGE_MOUSE_CURSOR_LABEL}, {"largeMouseCursorLabel", IDS_SETTINGS_LARGE_MOUSE_CURSOR_LABEL},
...@@ -344,6 +371,15 @@ void AddA11yStrings(content::WebUIDataSource* html_source) { ...@@ -344,6 +371,15 @@ void AddA11yStrings(content::WebUIDataSource* html_source) {
"showExperimentalA11yLabels", "showExperimentalA11yLabels",
base::FeatureList::IsEnabled(features::kExperimentalAccessibilityLabels)); base::FeatureList::IsEnabled(features::kExperimentalAccessibilityLabels));
html_source->AddBoolean(
"enableCaptionSettings",
base::FeatureList::IsEnabled(features::kCaptionSettings));
#if defined(OS_WIN)
html_source->AddBoolean("isWindows10OrNewer",
base::win::GetVersion() >= base::win::Version::WIN10);
#endif
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
html_source->AddString("accountManagerLearnMoreUrl", html_source->AddString("accountManagerLearnMoreUrl",
chrome::kAccountManagerLearnMoreURL); chrome::kAccountManagerLearnMoreURL);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "chrome/browser/ui/webui/settings/accessibility_main_handler.h" #include "chrome/browser/ui/webui/settings/accessibility_main_handler.h"
#include "chrome/browser/ui/webui/settings/appearance_handler.h" #include "chrome/browser/ui/webui/settings/appearance_handler.h"
#include "chrome/browser/ui/webui/settings/browser_lifetime_handler.h" #include "chrome/browser/ui/webui/settings/browser_lifetime_handler.h"
#include "chrome/browser/ui/webui/settings/captions_handler.h"
#include "chrome/browser/ui/webui/settings/downloads_handler.h" #include "chrome/browser/ui/webui/settings/downloads_handler.h"
#include "chrome/browser/ui/webui/settings/extension_control_handler.h" #include "chrome/browser/ui/webui/settings/extension_control_handler.h"
#include "chrome/browser/ui/webui/settings/font_handler.h" #include "chrome/browser/ui/webui/settings/font_handler.h"
...@@ -226,6 +227,10 @@ SettingsUI::SettingsUI(content::WebUI* web_ui) ...@@ -226,6 +227,10 @@ SettingsUI::SettingsUI(content::WebUI* web_ui)
AddSettingsPageUIHandler(std::make_unique<StartupPagesHandler>(web_ui)); AddSettingsPageUIHandler(std::make_unique<StartupPagesHandler>(web_ui));
AddSettingsPageUIHandler(std::make_unique<SecurityKeysHandler>()); AddSettingsPageUIHandler(std::make_unique<SecurityKeysHandler>());
#if defined(OS_WIN) || defined(OS_MACOSX)
AddSettingsPageUIHandler(std::make_unique<CaptionsHandler>());
#endif
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
// TODO(950007): Remove this when SplitSettings is the default and there are // TODO(950007): Remove this when SplitSettings is the default and there are
// no Chrome OS settings in the browser settings page. // no Chrome OS settings in the browser settings page.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment