Commit 8d66fe81 authored by Esmael El-Moslimany's avatar Esmael El-Moslimany Committed by Commit Bot

WebUI NTP: support dark mode OneGoogleBar

Bug: 1093315, b/158458370
Change-Id: Id7ef567eee4f4cd39cfe449c41af8613886a176b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2321229
Commit-Queue: Esmael Elmoslimany <aee@chromium.org>
Reviewed-by: default avatarTibor Goldschwendt <tiborg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#792772}
parent 4446b429
...@@ -19,6 +19,7 @@ js_type_check("closure_compile") { ...@@ -19,6 +19,7 @@ js_type_check("closure_compile") {
":grid", ":grid",
":iframe", ":iframe",
":logo", ":logo",
":one_google_bar_api",
":realbox", ":realbox",
":realbox_button", ":realbox_button",
":realbox_dropdown", ":realbox_dropdown",
...@@ -45,6 +46,7 @@ js_library("app") { ...@@ -45,6 +46,7 @@ js_library("app") {
":background_manager", ":background_manager",
":browser_proxy", ":browser_proxy",
":most_visited", ":most_visited",
":one_google_bar_api",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/js:event_tracker.m", "//ui/webui/resources/js:event_tracker.m",
"//ui/webui/resources/js:load_time_data.m", "//ui/webui/resources/js:load_time_data.m",
...@@ -209,6 +211,9 @@ js_library("background_manager") { ...@@ -209,6 +211,9 @@ js_library("background_manager") {
deps = [ ":utils" ] deps = [ ":utils" ]
} }
js_library("one_google_bar_api") {
}
html_to_js("web_components") { html_to_js("web_components") {
js_files = [ js_files = [
"app.js", "app.js",
......
...@@ -22,6 +22,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/poly ...@@ -22,6 +22,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/poly
import {BackgroundManager} from './background_manager.js'; import {BackgroundManager} from './background_manager.js';
import {BrowserProxy} from './browser_proxy.js'; import {BrowserProxy} from './browser_proxy.js';
import {BackgroundSelection, BackgroundSelectionType} from './customize_dialog.js'; import {BackgroundSelection, BackgroundSelectionType} from './customize_dialog.js';
import {oneGoogleBarApi} from './one_google_bar_api.js';
import {$$, hexColorToSkColor, skColorToRgba} from './utils.js'; import {$$, hexColorToSkColor, skColorToRgba} from './utils.js';
class AppElement extends PolymerElement { class AppElement extends PolymerElement {
...@@ -344,10 +345,11 @@ class AppElement extends PolymerElement { ...@@ -344,10 +345,11 @@ class AppElement extends PolymerElement {
document.body.appendChild(endOfBodyScript); document.body.appendChild(endOfBodyScript);
this.pageHandler_.onOneGoogleBarRendered(BrowserProxy.getInstance().now()); this.pageHandler_.onOneGoogleBarRendered(BrowserProxy.getInstance().now());
oneGoogleBarApi.trackDarkModeChanges();
} }
/** @private */ /** @private */
async onOneGoogleBarDarkThemeEnabledChange_() { onOneGoogleBarDarkThemeEnabledChange_() {
if (!this.oneGoogleBarLoaded_) { if (!this.oneGoogleBarLoaded_) {
return; return;
} }
...@@ -358,16 +360,7 @@ class AppElement extends PolymerElement { ...@@ -358,16 +360,7 @@ class AppElement extends PolymerElement {
}); });
return; return;
} }
const {gbar} = /** @type {{gbar}} */ (window); oneGoogleBarApi.setForegroundLight(this.oneGoogleBarDarkThemeEnabled_);
if (!gbar) {
return;
}
const oneGoogleBar =
await /** @type {!{a: {bf: function(): !Promise<{pc: !Function}>}}} */ (
gbar)
.a.bf();
oneGoogleBar.pc.call(
oneGoogleBar, this.oneGoogleBarDarkThemeEnabled_ ? 1 : 0);
} }
/** /**
......
...@@ -62,4 +62,6 @@ ...@@ -62,4 +62,6 @@
file="untrusted/background_image.html" type="BINDATA" /> file="untrusted/background_image.html" type="BINDATA" />
<include name="IDR_NEW_TAB_PAGE_UNTRUSTED_BACKGROUND_IMAGE_JS" <include name="IDR_NEW_TAB_PAGE_UNTRUSTED_BACKGROUND_IMAGE_JS"
file="untrusted/background_image.js" type="BINDATA" /> file="untrusted/background_image.js" type="BINDATA" />
<include name="IDR_NEW_TAB_PAGE_ONE_GOOGLE_BAR_API_JS"
file="one_google_bar_api.js" type="BINDATA" compress="false" />
</grit-part> </grit-part>
// Copyright 2020 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 This file provides a way to update the OneGoogleBar by using
* the underlying API exposed by the OneGoogleBar.
*/
/**
* @param {string} apiName
* @param {string} fnName
* @param {...*} args
* @return {!Promise}
*/
const callApi = async (apiName, fnName, ...args) => {
const {gbar} = /** @type {!{gbar}} */ (window);
if (!gbar) {
return;
}
const api = await gbar.a[apiName]();
return api[fnName].apply(api, args);
};
/**
* @type {!{
* bar: !{
* setForegroundStyle: function(number): !Promise,
* setBackgroundColor: function(string): !Promise,
* setDarkMode: function(boolean): !Promise,
* },
* }}
*/
const api = [{
name: 'bar',
apiName: 'bf',
fns: [
['setForegroundStyle', 'pc'],
['setBackgroundColor', 'pd'],
['setDarkMode', 'pp'],
],
}].reduce((topLevelApi, def) => {
topLevelApi[def.name] = def.fns.reduce((apiPart, [name, fnName]) => {
apiPart[name] = callApi.bind(null, def.apiName, fnName);
return apiPart;
}, {});
return topLevelApi;
}, {});
/** @return {!Promise} */
const updateDarkMode = async () => {
await api.bar.setDarkMode(
window.matchMedia('(prefers-color-scheme: dark)').matches);
// |setDarkMode(toggle)| updates the background color and foreground style.
// The background color should always be 'transparent'.
api.bar.setBackgroundColor('transparent');
// The foreground style is set based on NTP theme and not dark mode.
api.bar.setForegroundStyle(foregroundLight ? 1 : 0);
};
/** @type {boolean} */
let foregroundLight = false;
export const oneGoogleBarApi = {
/**
* Returns the last argument value passed into |setForegroundLight(enabled)|.
* @return {boolean}
*/
isForegroundLight: () => foregroundLight,
/**
* Updates the foreground on the OneGoogleBar to provide contrast against the
* background.
* @param {boolean} enabled
*/
setForegroundLight: enabled => {
foregroundLight = enabled;
api.bar.setForegroundStyle(foregroundLight ? 1 : 0);
},
/**
* Updates the OneGoogleBar dark mode when called as well as any time dark
* mode is updated.
* @type {!function()}
*/
trackDarkModeChanges: () => {
window.matchMedia('(prefers-color-scheme: dark)').addListener(() => {
updateDarkMode();
});
updateDarkMode();
},
};
...@@ -17,6 +17,6 @@ ...@@ -17,6 +17,6 @@
<script>$i18nRaw{afterBarScript}</script> <script>$i18nRaw{afterBarScript}</script>
$i18nRaw{endOfBodyHtml} $i18nRaw{endOfBodyHtml}
<script>$i18nRaw{endOfBodyScript}</script> <script>$i18nRaw{endOfBodyScript}</script>
<script src="one_google_bar.js"></script> <script type="module" src="one_google_bar.js"></script>
</body> </body>
</html> </html>
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import {oneGoogleBarApi} from './one_google_bar_api.js';
/** /**
* The following |messageType|'s are sent to the parent frame: * The following |messageType|'s are sent to the parent frame:
* - loaded: sent on initial load. * - loaded: sent on initial load.
...@@ -24,36 +26,16 @@ function postMessage(messageType, data) { ...@@ -24,36 +26,16 @@ function postMessage(messageType, data) {
'chrome://new-tab-page'); 'chrome://new-tab-page');
} }
// Object that exposes: /**
// - |getEnabled()|: returns whether dark theme is enabled. * Object that exposes:
// - |setEnabled(value)|: updates whether dark theme is enabled using the * - |track()|: sets up MutationObserver to track element visibility changes.
// OneGoogleBar API. * - |update(potentialNewOverlays)|: determines visibility of tracked elements
const darkTheme = (() => { * and sends an update to the top frame about element visibility.
let enabled = false; * @type {!{
* track: !function(),
/** @return {boolean} */ * update: !function(!Array<!Element>),
const getEnabled = () => enabled; * }}
*/
/**
* @param {boolean} value
* @return {!Promise}
*/
const setEnabled = async value => {
if (!window.gbar) {
return;
}
enabled = value;
const ogb = await window.gbar.a.bf();
ogb.pc.call(ogb, enabled ? 1 : 0);
};
return {getEnabled, setEnabled};
})();
// Object that exposes:
// - |track()|: sets up MutationObserver to track element visibility changes.
// - |update(potentialNewOverlays)|: determines visibility of tracked elements
// and sends an update to the top frame about element visibility.
const overlayUpdater = (() => { const overlayUpdater = (() => {
const modalOverlays = document.documentElement.hasAttribute('modal-overlays'); const modalOverlays = document.documentElement.hasAttribute('modal-overlays');
let shouldUndoDarkTheme = false; let shouldUndoDarkTheme = false;
...@@ -170,13 +152,13 @@ const overlayUpdater = (() => { ...@@ -170,13 +152,13 @@ const overlayUpdater = (() => {
// OneGoogleBar iframe. The dark theme for the OneGoogleBar is then enabled // OneGoogleBar iframe. The dark theme for the OneGoogleBar is then enabled
// for better visibility. // for better visibility.
if (overlayShown) { if (overlayShown) {
if (!darkTheme.getEnabled()) { if (!oneGoogleBarApi.isForegroundLight()) {
shouldUndoDarkTheme = true; shouldUndoDarkTheme = true;
darkTheme.setEnabled(true); oneGoogleBarApi.setForegroundLight(true);
} }
} else if (shouldUndoDarkTheme) { } else if (shouldUndoDarkTheme) {
shouldUndoDarkTheme = false; shouldUndoDarkTheme = false;
darkTheme.setEnabled(false); oneGoogleBarApi.setForegroundLight(false);
} }
}; };
...@@ -209,7 +191,7 @@ const overlayUpdater = (() => { ...@@ -209,7 +191,7 @@ const overlayUpdater = (() => {
window.addEventListener('message', ({data}) => { window.addEventListener('message', ({data}) => {
if (data.type === 'enableDarkTheme') { if (data.type === 'enableDarkTheme') {
darkTheme.setEnabled(data.enabled); oneGoogleBarApi.setForegroundLight(data.enabled);
} }
}); });
...@@ -233,7 +215,7 @@ document.addEventListener('DOMContentLoaded', () => { ...@@ -233,7 +215,7 @@ document.addEventListener('DOMContentLoaded', () => {
el.target = '_top'; el.target = '_top';
} }
}); });
modalOverlays = document.documentElement.hasAttribute('modal-overlays');
postMessage('loaded'); postMessage('loaded');
overlayUpdater.track(); overlayUpdater.track();
oneGoogleBarApi.trackDarkModeChanges();
}); });
...@@ -133,6 +133,12 @@ void UntrustedSource::StartDataRequest( ...@@ -133,6 +133,12 @@ void UntrustedSource::StartDataRequest(
IDR_NEW_TAB_PAGE_UNTRUSTED_ONE_GOOGLE_BAR_JS)); IDR_NEW_TAB_PAGE_UNTRUSTED_ONE_GOOGLE_BAR_JS));
return; return;
} }
if (path == "one_google_bar_api.js") {
ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
std::move(callback).Run(
bundle.LoadDataResourceBytes(IDR_NEW_TAB_PAGE_ONE_GOOGLE_BAR_API_JS));
return;
}
if (path == "promo" && promo_service_) { if (path == "promo" && promo_service_) {
promo_callbacks_.push_back(std::move(callback)); promo_callbacks_.push_back(std::move(callback));
if (promo_service_->promo_data().has_value()) { if (promo_service_->promo_data().has_value()) {
...@@ -209,11 +215,13 @@ void UntrustedSource::StartDataRequest( ...@@ -209,11 +215,13 @@ void UntrustedSource::StartDataRequest(
std::string UntrustedSource::GetMimeType(const std::string& path) { std::string UntrustedSource::GetMimeType(const std::string& path) {
const std::string stripped_path = path.substr(0, path.find("?")); const std::string stripped_path = path.substr(0, path.find("?"));
if (base::EndsWith(stripped_path, ".js", if (base::EndsWith(stripped_path, ".js",
base::CompareCase::INSENSITIVE_ASCII)) base::CompareCase::INSENSITIVE_ASCII)) {
return "application/javascript"; return "application/javascript";
}
if (base::EndsWith(stripped_path, ".jpg", if (base::EndsWith(stripped_path, ".jpg",
base::CompareCase::INSENSITIVE_ASCII)) base::CompareCase::INSENSITIVE_ASCII)) {
return "image/jpg"; return "image/jpg";
}
return "text/html"; return "text/html";
} }
...@@ -226,6 +234,10 @@ bool UntrustedSource::ShouldReplaceExistingSource() { ...@@ -226,6 +234,10 @@ bool UntrustedSource::ShouldReplaceExistingSource() {
return false; return false;
} }
bool UntrustedSource::ShouldServeMimeTypeAsContentTypeHeader() {
return true;
}
bool UntrustedSource::ShouldServiceRequest( bool UntrustedSource::ShouldServiceRequest(
const GURL& url, const GURL& url,
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
...@@ -237,7 +249,8 @@ bool UntrustedSource::ShouldServiceRequest( ...@@ -237,7 +249,8 @@ bool UntrustedSource::ShouldServiceRequest(
return path == "one-google-bar" || path == "one_google_bar.js" || return path == "one-google-bar" || path == "one_google_bar.js" ||
path == "promo" || path == "promo.js" || path == "image" || path == "promo" || path == "promo.js" || path == "image" ||
path == "background_image" || path == "custom_background_image" || path == "background_image" || path == "custom_background_image" ||
path == "background_image.js" || path == "background.jpg"; path == "background_image.js" || path == "background.jpg" ||
path == "one_google_bar_api.js";
} }
void UntrustedSource::OnOneGoogleBarDataUpdated() { void UntrustedSource::OnOneGoogleBarDataUpdated() {
......
...@@ -60,6 +60,7 @@ class UntrustedSource : public content::URLDataSource, ...@@ -60,6 +60,7 @@ class UntrustedSource : public content::URLDataSource,
std::string GetMimeType(const std::string& path) override; std::string GetMimeType(const std::string& path) override;
bool AllowCaching() override; bool AllowCaching() override;
bool ShouldReplaceExistingSource() override; bool ShouldReplaceExistingSource() override;
bool ShouldServeMimeTypeAsContentTypeHeader() override;
bool ShouldServiceRequest(const GURL& url, bool ShouldServiceRequest(const GURL& url,
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
int render_process_id) override; int render_process_id) override;
......
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