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

WebUI NTP: support OneGoogleBar modal and clipped overlays

Bug: 1084640
Change-Id: I21e89cbe3429c25f8a01f2cc0b79d5b5020c9024
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2209237
Commit-Queue: Esmael Elmoslimany <aee@chromium.org>
Auto-Submit: Esmael Elmoslimany <aee@chromium.org>
Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Reviewed-by: default avatarTibor Goldschwendt <tiborg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#770839}
parent 5781c3f0
......@@ -3669,6 +3669,11 @@ const FeatureEntry kFeatureEntries[] = {
flag_descriptions::kNtpIframeOneGoogleBarDescription, kOsDesktop,
FEATURE_VALUE_TYPE(ntp_features::kIframeOneGoogleBar)},
{"ntp-one-google-bar-modal-overlays",
flag_descriptions::kNtpOneGoogleBarModalOverlaysName,
flag_descriptions::kNtpOneGoogleBarModalOverlaysDescription, kOsDesktop,
FEATURE_VALUE_TYPE(ntp_features::kOneGoogleBarModalOverlays)},
{"ntp-realbox", flag_descriptions::kNtpRealboxName,
flag_descriptions::kNtpRealboxDescription, kOsDesktop,
FEATURE_VALUE_TYPE(ntp_features::kRealbox)},
......
......@@ -3090,6 +3090,11 @@
"owners": ["aee", "mahmadi", "tiborg"],
"expiry_milestone": 86
},
{
"name": "ntp-one-google-bar-modal-overlays",
"owners": ["aee", "mahmadi", "tiborg"],
"expiry_milestone": 86
},
{
"name": "ntp-realbox",
"owners": ["aee", "mahmadi", "tiborg"],
......
......@@ -2870,6 +2870,13 @@ const char kNtpIframeOneGoogleBarDescription[] =
"Enables loading the OneGoogleBar in an iframe. Otherwise, the "
"OneGoogleBar is loaded inline on chrome://new-tab-page.";
const char kNtpOneGoogleBarModalOverlaysName[] =
"When OneGoogleBar is loaded in an iframe, overlays are modal";
const char kNtpOneGoogleBarModalOverlaysDescription[] =
"Enables overlays being modal, when the OneGoogleBar is loaded as iframe."
"Otherwise, a clip-path definition is used to clip away parts of the"
"OneGoogleBar that do not have visible elements.";
const char kNtpRealboxName[] = "Real search box in New Tab Page";
const char kNtpRealboxDescription[] =
"Enables a search box in the middle of the NTP that will accept input "
......
......@@ -1658,6 +1658,9 @@ extern const char kNtpDismissPromosDescription[];
extern const char kNtpIframeOneGoogleBarName[];
extern const char kNtpIframeOneGoogleBarDescription[];
extern const char kNtpOneGoogleBarModalOverlaysName[];
extern const char kNtpOneGoogleBarModalOverlaysDescription[];
extern const char kNtpRealboxName[];
extern const char kNtpRealboxDescription[];
......
......@@ -18,12 +18,24 @@
}
#oneGoogleBar {
clip-path: url(#oneGoogleBarClipPath);
height: 100%;
position: absolute;
top: 0;
width: 100%;
z-index: 1000;
}
#oneGoogleBarOverlayBackdrop {
background: rgba(0, 0, 0, .6);
display: none;
height: 100%;
position: fixed;
top: 0;
width: 100%;
z-index: 999;
}
#oneGoogleBarOverlayBackdrop[show] {
display: block;
}
#content {
......@@ -297,6 +309,7 @@
</ntp-customize-dialog>
</template>
</dom-if>
<div id="oneGoogleBarOverlayBackdrop"></div>
<svg>
<defs>
<clipPath id="oneGoogleBarClipPath">
......
......@@ -49,6 +49,13 @@ class AppElement extends PolymerElement {
reflectToAttribute: true,
},
/** @private */
oneGoogleBarModalOverlaysEnabled_: {
type: Boolean,
value: () =>
loadTimeData.getBoolean('oneGoogleBarModalOverlaysEnabled'),
},
/** @private */
oneGoogleBarIframePath_: {
type: String,
......@@ -63,6 +70,7 @@ class AppElement extends PolymerElement {
/** @private */
oneGoogleBarLoaded_: {
observer: 'oneGoogleBarLoadedChange_',
type: Boolean,
value: false,
},
......@@ -589,13 +597,23 @@ class AppElement extends PolymerElement {
/**
* Handles messages from the OneGoogleBar iframe. The messages that are
* handled include show bar on load and overlay updates.
*
* 'overlaysUpdated' message includes the updated array of overlay rects that
* are shown.
*
* When modal overlays are enabled, activate/deactivate controls if the
* OneGoogleBar is layered on top of #content with a backdrop. This would
* happen when OneGoogleBar has an overlay open.
* @param {!Object} data
* @private
*/
handleOneGoogleBarMessage_(data) {
if (data.messageType === 'loaded') {
if (!this.oneGoogleBarModalOverlaysEnabled_) {
const oneGoogleBar = $$(this, '#oneGoogleBar');
oneGoogleBar.style.clipPath = 'url(#oneGoogleBarClipPath)';
oneGoogleBar.style.zIndex = '1000';
}
this.oneGoogleBarLoaded_ = true;
BrowserProxy.getInstance().handler.onOneGoogleBarRendered(
BrowserProxy.getInstance().now());
......@@ -615,6 +633,12 @@ class AppElement extends PolymerElement {
rectElement.setAttribute('height', height + 16);
this.$.oneGoogleBarClipPath.appendChild(rectElement);
});
} else if (data.messageType === 'activate') {
this.$.oneGoogleBarOverlayBackdrop.toggleAttribute('show', true);
$$(this, '#oneGoogleBar').style.zIndex = '1000';
} else if (data.messageType === 'deactivate') {
this.$.oneGoogleBarOverlayBackdrop.toggleAttribute('show', false);
$$(this, '#oneGoogleBar').style.zIndex = '0';
}
}
......@@ -643,6 +667,58 @@ class AppElement extends PolymerElement {
}
}
/** @private */
oneGoogleBarLoadedChange_() {
if (this.oneGoogleBarLoaded_ && this.iframeOneGoogleBarEnabled_ &&
this.oneGoogleBarModalOverlaysEnabled_) {
this.setupShortcutDragDropOneGoogleBarWorkaround_();
}
}
/**
* During a shortcut drag, an iframe behind ntp-most-visited will prevent
* 'dragover' events from firing. To workaround this, 'pointer-events: none'
* can be set on the iframe. When doing this after the 'dragstart' event is
* fired is too late. We can instead set 'pointer-events: none' when the
* pointer enters ntp-most-visited.
*
* 'pointerenter' and pointerleave' events fire during drag. The iframe
* 'pointer-events' needs to be reset to the original value when 'dragend'
* fires if the pointer has left ntp-most-visited.
* @private
*/
setupShortcutDragDropOneGoogleBarWorkaround_() {
const iframe = $$(this, '#oneGoogleBar');
let resetAtDragEnd = false;
let dragging = false;
let originalPointerEvents;
this.eventTracker_.add(this.$.mostVisited, 'pointerenter', () => {
if (dragging) {
resetAtDragEnd = false;
return;
}
originalPointerEvents = getComputedStyle(iframe).pointerEvents;
iframe.style.pointerEvents = 'none';
});
this.eventTracker_.add(this.$.mostVisited, 'pointerleave', () => {
if (dragging) {
resetAtDragEnd = true;
return;
}
iframe.style.pointerEvents = originalPointerEvents;
});
this.eventTracker_.add(this.$.mostVisited, 'dragstart', () => {
dragging = true;
});
this.eventTracker_.add(this.$.mostVisited, 'dragend', () => {
dragging = false;
if (resetAtDragEnd) {
resetAtDragEnd = false;
iframe.style.pointerEvents = originalPointerEvents;
}
});
}
/** @private */
printPerformanceDatum_(name, time, auxTime = 0) {
if (!this.shouldPrintPerformance_) {
......
<!doctype html>
<html dir="$i18n{textdirection}">
<html dir="$i18n{textdirection}" $i18n{modalOverlays}>
<head>
<meta charset="utf-8">
<style>
......
......@@ -3,6 +3,9 @@
// found in the LICENSE file.
const oneGoogleBarHeightInPixels = 64;
let modalOverlays = false;
let darkThemeEnabled = false;
let shouldUndoDarkTheme = false;
/**
* @param {boolean} enabled
......@@ -12,6 +15,7 @@ async function enableDarkTheme(enabled) {
if (!window.gbar) {
return;
}
darkThemeEnabled = enabled;
const ogb = await window.gbar.a.bf();
ogb.pc.call(ogb, enabled ? 1 : 0);
}
......@@ -21,6 +25,11 @@ async function enableDarkTheme(enabled) {
* - loaded: sent on initial load.
* - overlaysUpdated: sent when an overlay is updated. The overlay bounding
* rects are included in the |data|.
* - activate/deactivate: When an overlay is open, 'activate' is sent to the
* to ntp-app so it can layer the OneGoogleBar over the NTP content. When
* no overlays are open, 'deactivate' is sent to ntp-app so the NTP
* content can be on top. The top bar of the OneGoogleBar is always on
* top.
* @param {string} messageType
* @param {Object} data
*/
......@@ -68,7 +77,24 @@ function sendOverlayUpdate() {
return true;
})
.map(el => el.getBoundingClientRect());
postMessage('overlaysUpdated', overlayRects);
if (!modalOverlays) {
postMessage('overlaysUpdated', overlayRects);
return;
}
const overlayShown = overlayRects.length > 0;
postMessage(overlayShown ? 'activate' : 'deactivate');
// If the overlays are modal, a dark backdrop is displayed below the
// OneGoogleBar iframe. The dark theme for the OneGoogleBar is then enabled
// for better visibility.
if (overlayShown) {
if (!darkThemeEnabled) {
shouldUndoDarkTheme = true;
enableDarkTheme(true);
}
} else if (shouldUndoDarkTheme) {
shouldUndoDarkTheme = false;
enableDarkTheme(false);
}
}
function trackOverlayState() {
......@@ -89,6 +115,12 @@ function trackOverlayState() {
overlays.has(target)) {
return;
}
// When overlays are modal, the tooltips should not be treated like an
// overlay.
if (modalOverlays && target.parentElement &&
target.parentElement.tagName === 'BODY') {
return;
}
if (target.offsetTop + target.offsetHeight > oneGoogleBarHeightInPixels) {
overlays.add(target);
}
......@@ -133,6 +165,7 @@ document.addEventListener('DOMContentLoaded', () => {
el.target = '_top';
}
});
modalOverlays = document.documentElement.hasAttribute('modal-overlays');
postMessage('loaded');
trackOverlayState();
});
......@@ -26,6 +26,11 @@ const base::Feature kDismissPromos{"DismissNtpPromos",
const base::Feature kIframeOneGoogleBar{"IframeOneGoogleBar",
base::FEATURE_DISABLED_BY_DEFAULT};
// If enabled, the iframed OneGooleBar shows the overlays modally with a
// backdrop.
const base::Feature kOneGoogleBarModalOverlays{
"OneGoogleBarModalOverlays", base::FEATURE_DISABLED_BY_DEFAULT};
// Depends on kRealbox being enabled. If enabled, the NTP "realbox" will be
// themed like the omnibox (same background/text/selected/hover colors).
const base::Feature kRealboxMatchOmniboxTheme{
......
......@@ -15,6 +15,7 @@ namespace ntp_features {
extern const base::Feature kConfirmSuggestionRemovals;
extern const base::Feature kDismissPromos;
extern const base::Feature kIframeOneGoogleBar;
extern const base::Feature kOneGoogleBarModalOverlays;
extern const base::Feature kRealboxMatchOmniboxTheme;
extern const base::Feature kRealboxUseGoogleGIcon;
extern const base::Feature kWebUI;
......
......@@ -78,6 +78,9 @@ content::WebUIDataSource* CreateNewTabPageUiHtmlSource(Profile* profile) {
source->AddBoolean(
"iframeOneGoogleBarEnabled",
base::FeatureList::IsEnabled(ntp_features::kIframeOneGoogleBar));
source->AddBoolean(
"oneGoogleBarModalOverlaysEnabled",
base::FeatureList::IsEnabled(ntp_features::kOneGoogleBarModalOverlays));
static constexpr webui::LocalizedString kStrings[] = {
{"doneButton", IDS_DONE},
......
......@@ -19,6 +19,7 @@
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/ntp_features.h"
#include "chrome/browser/search/one_google_bar/one_google_bar_data.h"
#include "chrome/browser/search/one_google_bar/one_google_bar_service_factory.h"
#include "chrome/browser/search/promos/promo_data.h"
......@@ -249,6 +250,10 @@ void UntrustedSource::OnOneGoogleBarDataUpdated() {
if (data.has_value()) {
ui::TemplateReplacements replacements;
replacements["textdirection"] = base::i18n::IsRTL() ? "rtl" : "ltr";
replacements["modalOverlays"] =
base::FeatureList::IsEnabled(ntp_features::kOneGoogleBarModalOverlays)
? "modal-overlays"
: "";
replacements["barHtml"] = data->bar_html;
replacements["inHeadScript"] = data->in_head_script;
replacements["inHeadStyle"] = data->in_head_style;
......
......@@ -38588,6 +38588,7 @@ from previous Chrome versions.
<int value="-1842511843" label="DiceWebSigninInterception:enabled"/>
<int value="-1840608422" label="AdvancedPpdAttributes:disabled"/>
<int value="-1839874877" label="WebXROrientationSensorDevice:enabled"/>
<int value="-1839540507" label="OneGoogleBarModalOverlays:enabled"/>
<int value="-1839496458" label="disable-file-manager-touch-mode"/>
<int value="-1838482444" label="disable-settings-window"/>
<int value="-1837401779" label="EnableFileManagerFormatDialog:enabled"/>
......@@ -41156,6 +41157,7 @@ from previous Chrome versions.
<int value="1095706700" label="NavigationPredictor:enabled"/>
<int value="1096477444" label="AssistantVoiceMatch:enabled"/>
<int value="1097935876" label="CrostiniShowMicSetting:enabled"/>
<int value="1097981222" label="OneGoogleBarModalOverlays:disabled"/>
<int value="1098823967" label="ash-enable-window-cycle-ui"/>
<int value="1100244809" label="MacSystemMediaPermissionsInfoUI:disabled"/>
<int value="1101062411" label="Rar2Fs:disabled"/>
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