Commit ac5683fd authored by Tibor Goldschwendt's avatar Tibor Goldschwendt Committed by Commit Bot

[webui-ntp] Add background collection previews to customize dialog

NOTE: this does not embed actual images as we cannot embed external
content in a WebUI yet.

Bug: 1032328
Change-Id: I5bb07e9b5a699b8e3fd3360ff4498475212a6026
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2005811
Commit-Queue: Tibor Goldschwendt <tiborg@chromium.org>
Commit-Queue: Alex Gough <ajgo@chromium.org>
Auto-Submit: Tibor Goldschwendt <tiborg@chromium.org>
Reviewed-by: default avatarAlex Gough <ajgo@chromium.org>
Reviewed-by: default avatarEsmael Elmoslimany <aee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#742936}
parent 1c1e1add
......@@ -51,6 +51,7 @@ js_library("most_visited") {
js_library("customize_dialog") {
deps = [
":customize_backgrounds",
":customize_shortcuts",
":customize_themes",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
......@@ -59,6 +60,12 @@ js_library("customize_dialog") {
]
}
js_library("customize_backgrounds") {
deps = [
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
]
}
js_library("customize_themes") {
deps = [
":grid",
......@@ -132,6 +139,12 @@ polymer_modulizer("customize_shortcuts") {
html_type = "v3-ready"
}
polymer_modulizer("customize_backgrounds") {
js_file = "customize_backgrounds.js"
html_file = "customize_backgrounds.html"
html_type = "v3-ready"
}
polymer_modulizer("customize_themes") {
js_file = "customize_themes.js"
html_file = "customize_themes.html"
......@@ -159,6 +172,7 @@ polymer_modulizer("voice_search_overlay") {
group("polymer3_elements") {
deps = [
":app_module",
":customize_backgrounds_module",
":customize_dialog_module",
":customize_shortcuts_module",
":customize_themes_module",
......
<style>
#collections {
--ntp-grid-gap: 8px;
padding: 4px;
}
.tile {
cursor: pointer;
outline-width: 0;
}
:host-context(.focus-outline-visible) .tile:focus {
box-shadow: 0 0 0 2px var(--ntp-focus-shadow-color);
}
.image {
border: none;
border-radius: 4px;
display: block;
height: 176px;
width: 176px;
}
/* TODO(crbug.com/1032328): This rule makes the URL somewhat readable. Remove
* once we show the actual image. */
.image {
background-color: var(--ntp-active-background-color);
color: var(--ntp-primary-text-color);
word-break: break-all;
}
.label {
color: var(--ntp-primary-text-color);
margin-bottom: 4px;
margin-top: 3px;
min-height: 30px;
}
</style>
<ntp-grid id="collections" columns="3">
<dom-repeat items="[[collections_]]">
<template>
<div class="tile" tabindex="0" title="[[item.label]]" role="button">
<!-- TODO(crbug.com/1032328): Show image in an iframe. -->
<div class="image">[[item.previewImageUrl.url]]</div>
<div class="label">[[item.label]]</div>
</div>
</template>
</dom-repeat>
</ntp-grid>
// 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.
import './grid.js';
import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {BrowserProxy} from './browser_proxy.js';
/** Element that lets the user configure the background. */
class CustomizeBackgroundsElement extends PolymerElement {
static get is() {
return 'ntp-customize-backgrounds';
}
static get template() {
return html`{__html_template__}`;
}
static get properties() {
return {
/** @private {!Array<!newTabPage.mojom.BackgroundCollection>} */
collections_: Array,
};
}
constructor() {
super();
BrowserProxy.getInstance().handler.getBackgroundCollections().then(
({collections}) => {
this.collections_ = collections;
});
}
}
customElements.define(
CustomizeBackgroundsElement.is, CustomizeBackgroundsElement);
......@@ -25,6 +25,7 @@
#menuContainer,
#pagesContainer {
max-height: 391px;
overflow: hidden;
}
......@@ -152,9 +153,8 @@
<div id="pagesContainer">
<div id="pages">
<iron-pages selected="[[selectedPage_]]" attr-for-selected="page-name">
<!-- TODO(crbug.com/1032328): Add support for selecting background
image. -->
<div page-name="backgrounds">backgrounds</div>
<ntp-customize-backgrounds page-name="backgrounds">
</ntp-customize-backgrounds>
<ntp-customize-shortcuts page-name="shortcuts">
</ntp-customize-shortcuts>
<ntp-customize-themes page-name="themes" theme="[[theme]]">
......
......@@ -6,6 +6,7 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
import 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js';
import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
import './customize_backgrounds.js';
import './customize_shortcuts.js';
import './customize_themes.js';
......
......@@ -30,6 +30,9 @@
<include name="IDR_NEW_TAB_PAGE_VOICE_SEARCH_OVERLAY_JS"
file="${root_gen_dir}/chrome/browser/resources/new_tab_page/voice_search_overlay.js"
use_base_dir="false" type="BINDATA" compress="gzip" />
<include name="IDR_NEW_TAB_PAGE_CUSTOMIZE_BACKGROUNDS_JS"
file="${root_gen_dir}/chrome/browser/resources/new_tab_page/customize_backgrounds.js"
use_base_dir="false" type="BINDATA" compress="gzip" />
<include name="IDR_NEW_TAB_PAGE_CUSTOMIZE_SHORTCUTS_JS"
file="${root_gen_dir}/chrome/browser/resources/new_tab_page/customize_shortcuts.js"
use_base_dir="false" type="BINDATA" compress="gzip" />
......
......@@ -27,6 +27,14 @@ struct ThemeColors {
skia.mojom.SkColor active_tab;
};
// A collection of background images.
struct BackgroundCollection {
// Localized string of the collection name.
string label;
// URL to a preview image for the collection. Can point to untrusted content.
url.mojom.Url preview_image_url;
};
// A predefined theme provided by Chrome. Created from data embedded in the
// Chrome binary.
struct ChromeTheme {
......@@ -117,6 +125,8 @@ interface PageHandler {
ConfirmThemeChanges();
// Reverts changes made to the theme.
RevertThemeChanges();
// Returns the collections of background images.
GetBackgroundCollections() => (array<BackgroundCollection> collections);
};
// WebUI-side handler for requests from the browser.
......
......@@ -8,6 +8,8 @@
#include "base/i18n/rtl.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/background/ntp_background_service.h"
#include "chrome/browser/search/background/ntp_background_service_factory.h"
#include "chrome/browser/search/chrome_colors/chrome_colors_factory.h"
#include "chrome/browser/search/chrome_colors/chrome_colors_service.h"
#include "chrome/browser/search/instant_service.h"
......@@ -65,14 +67,20 @@ NewTabPageHandler::NewTabPageHandler(
: chrome_colors_service_(
chrome_colors::ChromeColorsFactory::GetForProfile(profile)),
instant_service_(InstantServiceFactory::GetForProfile(profile)),
ntp_background_service_(
NtpBackgroundServiceFactory::GetForProfile(profile)),
page_{std::move(pending_page)},
receiver_{this, std::move(pending_page_handler)} {
CHECK(instant_service_);
CHECK(ntp_background_service_);
instant_service_->AddObserver(this);
ntp_background_service_->AddObserver(this);
page_->SetTheme(MakeTheme(*instant_service_->GetInitializedNtpTheme()));
}
NewTabPageHandler::~NewTabPageHandler() {
instant_service_->RemoveObserver(this);
ntp_background_service_->RemoveObserver(this);
}
void NewTabPageHandler::AddMostVisitedTile(
......@@ -194,6 +202,17 @@ void NewTabPageHandler::UpdateMostVisitedTile(
std::move(callback).Run(success);
}
void NewTabPageHandler::GetBackgroundCollections(
GetBackgroundCollectionsCallback callback) {
if (!ntp_background_service_) {
std::move(callback).Run(
std::vector<new_tab_page::mojom::BackgroundCollectionPtr>());
return;
}
background_collections_callback_ = std::move(callback);
ntp_background_service_->FetchCollectionInfo();
}
void NewTabPageHandler::NtpThemeChanged(const NtpTheme& ntp_theme) {
page_->SetTheme(MakeTheme(ntp_theme));
}
......@@ -220,3 +239,27 @@ void NewTabPageHandler::MostVisitedInfoChanged(
result->visible = info.is_visible;
page_->SetMostVisitedInfo(std::move(result));
}
void NewTabPageHandler::OnCollectionInfoAvailable() {
if (!background_collections_callback_) {
return;
}
std::vector<new_tab_page::mojom::BackgroundCollectionPtr> collections;
for (const auto& info : ntp_background_service_->collection_info()) {
auto collection = new_tab_page::mojom::BackgroundCollection::New();
collection->label = info.collection_name;
collection->preview_image_url = GURL(info.preview_image_url);
collections.push_back(std::move(collection));
}
std::move(background_collections_callback_).Run(std::move(collections));
}
void NewTabPageHandler::OnCollectionImagesAvailable() {}
void NewTabPageHandler::OnNextCollectionImageAvailable() {}
void NewTabPageHandler::OnNtpBackgroundServiceShuttingDown() {
ntp_background_service_->RemoveObserver(this);
ntp_background_service_ = nullptr;
}
......@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/search/background/ntp_background_service_observer.h"
#include "chrome/browser/search/instant_service_observer.h"
#include "chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom.h"
#include "chrome/common/search/instant_types.h"
......@@ -18,6 +19,7 @@
class GURL;
class InstantService;
class NtpBackgroundService;
class Profile;
namespace chrome_colors {
......@@ -26,7 +28,8 @@ class ChromeColorsService;
class NewTabPageHandler : public content::WebContentsObserver,
public new_tab_page::mojom::PageHandler,
public InstantServiceObserver {
public InstantServiceObserver,
public NtpBackgroundServiceObserver {
public:
NewTabPageHandler(mojo::PendingReceiver<new_tab_page::mojom::PageHandler>
pending_page_handler,
......@@ -54,15 +57,25 @@ class NewTabPageHandler : public content::WebContentsObserver,
void ConfirmThemeChanges() override;
void GetChromeThemes(GetChromeThemesCallback callback) override;
void RevertThemeChanges() override;
void GetBackgroundCollections(
GetBackgroundCollectionsCallback callback) override;
private:
// InstantServiceObserver:
void NtpThemeChanged(const NtpTheme& theme) override;
void MostVisitedInfoChanged(const InstantMostVisitedInfo& info) override;
// NtpBackgroundServiceObserver:
void OnCollectionInfoAvailable() override;
void OnCollectionImagesAvailable() override;
void OnNextCollectionImageAvailable() override;
void OnNtpBackgroundServiceShuttingDown() override;
chrome_colors::ChromeColorsService* chrome_colors_service_;
InstantService* instant_service_;
NtpBackgroundService* ntp_background_service_;
GURL last_blacklisted_;
GetBackgroundCollectionsCallback background_collections_callback_;
mojo::Remote<new_tab_page::mojom::Page> page_;
mojo::Receiver<new_tab_page::mojom::PageHandler> receiver_;
......
......@@ -22,6 +22,9 @@ suite('NewTabPageAppTest', () => {
PolymerTest.clearBody();
testProxy = createTestProxy();
testProxy.handler.setResultFor('getBackgroundCollections', Promise.resolve({
collections: [],
}));
testProxy.handler.setResultFor('getChromeThemes', Promise.resolve({
chromeThemes: [],
}));
......
// 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.
import 'chrome://new-tab-page/customize_backgrounds.js';
import {BrowserProxy} from 'chrome://new-tab-page/browser_proxy.js';
import {createTestProxy} from 'chrome://test/new_tab_page/test_support.js';
import {flushTasks} from 'chrome://test/test_util.m.js';
suite('NewTabPageCustomizeBackgroundsTest', () => {
/** @type {TestProxy} */
let testProxy;
setup(() => {
PolymerTest.clearBody();
testProxy = createTestProxy();
BrowserProxy.instance_ = testProxy;
});
test('creating element shows background collection tiles', async () => {
// Arrange.
const collections = [
{
label: 'collection_0',
previewImageUrl: {url: 'https://example.com/image_0.jpg'},
},
{
label: 'collection_1',
previewImageUrl: {url: 'https://example.com/image_1.jpg'},
},
];
const getBackgroundCollectionsCalled =
testProxy.handler.whenCalled('getBackgroundCollections');
testProxy.handler.setResultFor('getBackgroundCollections', Promise.resolve({
collections: collections,
}));
// Act.
const customizeBackgrounds =
document.createElement('ntp-customize-backgrounds');
document.body.appendChild(customizeBackgrounds);
await getBackgroundCollectionsCalled;
await flushTasks();
// Assert.
const tiles = customizeBackgrounds.shadowRoot.querySelectorAll('.tile');
assertEquals(tiles.length, 2);
assertEquals(tiles[0].getAttribute('title'), 'collection_0');
assertEquals(tiles[1].getAttribute('title'), 'collection_1');
assertEquals(
tiles[0].querySelector('.image').textContent.trim(),
'https://example.com/image_0.jpg');
assertEquals(
tiles[1].querySelector('.image').textContent.trim(),
'https://example.com/image_1.jpg');
});
});
......@@ -4,6 +4,8 @@
import 'chrome://new-tab-page/customize_dialog.js';
import {BrowserProxy} from 'chrome://new-tab-page/browser_proxy.js';
import {createTestProxy} from 'chrome://test/new_tab_page/test_support.js';
import {flushTasks, waitAfterNextRender} from 'chrome://test/test_util.m.js';
suite('NewTabPageCustomizeDialogTest', () => {
......@@ -13,6 +15,15 @@ suite('NewTabPageCustomizeDialogTest', () => {
setup(() => {
PolymerTest.clearBody();
const testProxy = createTestProxy();
testProxy.handler.setResultFor('getBackgroundCollections', Promise.resolve({
collections: [],
}));
testProxy.handler.setResultFor('getChromeThemes', Promise.resolve({
chromeThemes: [],
}));
BrowserProxy.instance_ = testProxy;
customizeDialog = document.createElement('ntp-customize-dialog');
document.body.appendChild(customizeDialog);
return flushTasks();
......
......@@ -111,6 +111,18 @@ TEST_F('NewTabPageCustomizeShortcutsTest', 'All', function() {
mocha.run();
});
// eslint-disable-next-line no-var
var NewTabPageCustomizeBackgroundsTest = class extends NewTabPageBrowserTest {
/** @override */
get browsePreload() {
return 'chrome://new-tab-page/test_loader.html?module=new_tab_page/customize_backgrounds_test.js';
}
};
TEST_F('NewTabPageCustomizeBackgroundsTest', 'All', function() {
mocha.run();
});
// eslint-disable-next-line no-var
var NewTabPageVoiceSearchOverlayTest = class extends NewTabPageBrowserTest {
/** @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