Commit cf42dd28 authored by kristipark's avatar kristipark Committed by Commit Bot

Add fallback icon support to MV tiles

Tiles with missing/small favicons will display fallback icons instead, which consists of a colored circle and the first letter of the tile title. The fallback color will either be gray for missing favicons or the dominant color of the small favicon.

This change depends on https://crrev.com/c/1096670.

Screenshot: https://screenshot.googleplex.com/dbu8dxk97sX.png

Bug: 837798
Cq-Include-Trybots: luci.chromium.try:closure_compilation
Change-Id: Ie6ddf538396bcf8fbfd11cb9e9f0bad075301edd
Reviewed-on: https://chromium-review.googlesource.com/1096680
Commit-Queue: Kristi Park <kristipark@chromium.org>
Reviewed-by: default avatarMarc Treib <treib@chromium.org>
Reviewed-by: default avatarEmily Stark <estark@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567493}
parent aee2f86a
......@@ -483,6 +483,25 @@ body.dark-theme .md-tile:active .md-menu::after {
display: none;
}
.md-favicon.fallback {
align-items: center;
border-radius: 50%;
display: flex;
height: 24px;
justify-content: center;
width: 24px;
}
.fallback-letter {
color: white;
font-family: Roboto;
font-size: 12px;
height: 16px;
line-height: 16px;
text-align: center;
width: 16px;
}
.md-title-container {
overflow: hidden;
}
......
......@@ -14,6 +14,8 @@
*/
const CLASSES = {
FAILED_FAVICON: 'failed-favicon', // Applied when the favicon fails to load.
FALLBACK: 'fallback',
FALLBACK_LETTER: 'fallback-letter',
MATERIAL_DESIGN: 'md', // Applies Material Design styles to the page.
// Material Design classes.
MD_EMPTY_TILE: 'md-empty-tile',
......@@ -373,6 +375,18 @@ var isSchemeAllowed = function(url) {
};
/**
* Converts an Array of color components into RGBA format "rgba(R,G,B,A)".
* @param {Array<number>} color Array of rgba color components.
* @return {string} CSS color in RGBA format.
* @private
*/
function convertToRGBAColor(color) {
return 'rgba(' + color[0] + ',' + color[1] + ',' + color[2] + ',' +
color[3] / 255 + ')';
}
/**
* Renders a MostVisited tile to the DOM.
* @param {object} data Object containing rid, url, title, favicon, thumbnail.
......@@ -601,6 +615,8 @@ function renderMaterialDesignTile(data) {
let mdFavicon = document.createElement('div');
mdFavicon.className = CLASSES.MD_FAVICON;
// Determine if a fallback icon should be displayed instead.
if (!data.fallbackBackgroundColorRgba || !data.fallbackTextColorRgba) {
let fi = document.createElement('img');
fi.src = data.faviconUrl;
// Set title and alt to empty so screen readers won't say the image name.
......@@ -613,8 +629,9 @@ function renderMaterialDesignTile(data) {
logMostVisitedImpression(
position, data.tileTitleSource, data.tileSource, tileType,
data.dataGenerationTime);
// Note: It's important to call countLoad last, because that might emit the
// NTP_ALL_TILES_LOADED event, which must happen after the impression log.
// Note: It's important to call countLoad last, because that might emit
// the NTP_ALL_TILES_LOADED event, which must happen after the impression
// log.
countLoad();
});
fi.addEventListener('error', function(ev) {
......@@ -625,11 +642,23 @@ function renderMaterialDesignTile(data) {
logMostVisitedImpression(
position, data.tileTitleSource, data.tileSource, tileType,
data.dataGenerationTime);
// Note: It's important to call countLoad last, because that might emit the
// NTP_ALL_TILES_LOADED event, which must happen after the impression log.
// Note: It's important to call countLoad last, because that might emit
// the NTP_ALL_TILES_LOADED event, which must happen after the impression
// log.
countLoad();
});
mdFavicon.appendChild(fi);
} else {
mdIconBackground.style.backgroundColor =
convertToRGBAColor(data.fallbackBackgroundColorRgba);
mdFavicon.classList.add(CLASSES.FALLBACK);
let fallbackLetter = document.createElement('div');
fallbackLetter.className = CLASSES.FALLBACK_LETTER;
fallbackLetter.style.color = convertToRGBAColor(data.fallbackTextColorRgba);
fallbackLetter.innerText = data.title.charAt(0);
mdFavicon.appendChild(fallbackLetter);
}
mdIconBackground.appendChild(mdFavicon);
mdIcon.appendChild(mdIconBackground);
mdTileInner.appendChild(mdIcon);
......
......@@ -36,6 +36,22 @@
#include "content/public/browser/url_data_source.h"
#include "ui/gfx/color_utils.h"
namespace {
const int kSectionBorderAlphaTransparency = 80;
// Converts SkColor to RGBAColor
RGBAColor SkColorToRGBAColor(const SkColor& skColor) {
RGBAColor color;
color.r = SkColorGetR(skColor);
color.g = SkColorGetG(skColor);
color.b = SkColorGetB(skColor);
color.a = SkColorGetA(skColor);
return color;
}
} // namespace
InstantService::InstantService(Profile* profile) : profile_(profile) {
// The initialization below depends on a typical set of browser threads. Skip
// it if we are running in a unit test without the full suite.
......@@ -226,6 +242,12 @@ void InstantService::OnURLsAvailable(
item.source = tile.source;
item.title_source = tile.title_source;
item.data_generation_time = tile.data_generation_time;
if (tile.has_fallback_style) {
item.has_fallback_style = true;
item.fallback_background_color =
SkColorToRGBAColor(tile.fallback_background_color);
item.fallback_text_color = SkColorToRGBAColor(tile.fallback_text_color);
}
most_visited_items_.push_back(item);
}
......@@ -244,22 +266,6 @@ void InstantService::NotifyAboutThemeInfo() {
observer.ThemeInfoChanged(*theme_info_);
}
namespace {
const int kSectionBorderAlphaTransparency = 80;
// Converts SkColor to RGBAColor
RGBAColor SkColorToRGBAColor(const SkColor& sKColor) {
RGBAColor color;
color.r = SkColorGetR(sKColor);
color.g = SkColorGetG(sKColor);
color.b = SkColorGetB(sKColor);
color.a = SkColorGetA(sKColor);
return color;
}
} // namespace
void InstantService::BuildThemeInfo() {
// Get theme information from theme service.
theme_info_.reset(new ThemeBackgroundInfo());
......
......@@ -47,6 +47,9 @@ IPC_STRUCT_TRAITS_BEGIN(InstantMostVisitedItem)
IPC_STRUCT_TRAITS_MEMBER(title)
IPC_STRUCT_TRAITS_MEMBER(thumbnail)
IPC_STRUCT_TRAITS_MEMBER(favicon)
IPC_STRUCT_TRAITS_MEMBER(has_fallback_style)
IPC_STRUCT_TRAITS_MEMBER(fallback_background_color)
IPC_STRUCT_TRAITS_MEMBER(fallback_text_color)
IPC_STRUCT_TRAITS_MEMBER(title_source)
IPC_STRUCT_TRAITS_MEMBER(source)
IPC_STRUCT_TRAITS_MEMBER(data_generation_time)
......
......@@ -56,10 +56,20 @@ bool ThemeBackgroundInfo::operator==(const ThemeBackgroundInfo& rhs) const {
}
InstantMostVisitedItem::InstantMostVisitedItem()
: title_source(ntp_tiles::TileTitleSource::UNKNOWN),
: has_fallback_style(false),
title_source(ntp_tiles::TileTitleSource::UNKNOWN),
source(ntp_tiles::TileSource::TOP_SITES) {}
InstantMostVisitedItem::InstantMostVisitedItem(
const InstantMostVisitedItem& other) = default;
InstantMostVisitedItem::~InstantMostVisitedItem() {}
bool InstantMostVisitedItem::IsEquivalentTo(
const InstantMostVisitedItem& rhs) const {
return url == rhs.url && title == rhs.title && thumbnail == rhs.thumbnail &&
favicon == rhs.favicon &&
has_fallback_style == rhs.has_fallback_style &&
fallback_background_color == rhs.fallback_background_color &&
fallback_text_color == rhs.fallback_text_color;
}
......@@ -115,6 +115,8 @@ struct InstantMostVisitedItem {
InstantMostVisitedItem(const InstantMostVisitedItem& other);
~InstantMostVisitedItem();
bool IsEquivalentTo(const InstantMostVisitedItem& rhs) const;
// The URL of the Most Visited item.
GURL url;
......@@ -128,6 +130,15 @@ struct InstantMostVisitedItem {
// The external URL of the favicon associated with this page.
GURL favicon;
// True if a fallback icon should be used.
bool has_fallback_style;
// The fallback icon background color in RGBA format.
RGBAColor fallback_background_color;
// The fallback icon text color in RGBA format.
RGBAColor fallback_text_color;
// The source of the item's |title|.
ntp_tiles::TileTitleSource title_source;
......
......@@ -41,8 +41,7 @@ bool AreMostVisitedItemsEqual(
return false;
for (size_t i = 0; i < new_items.size(); ++i) {
if (new_items[i].url != old_item_id_pairs[i].second.url ||
new_items[i].title != old_item_id_pairs[i].second.title) {
if (!new_items[i].IsEquivalentTo(old_item_id_pairs[i].second)) {
return false;
}
}
......
......@@ -184,6 +184,15 @@ v8::Local<v8::Object> GenerateMostVisitedItemData(
if (!mv_item.favicon.spec().empty())
builder.Set("faviconUrl", mv_item.favicon.spec());
if (mv_item.has_fallback_style) {
builder.Set(
"fallbackBackgroundColorRgba",
internal::RGBAColorToArray(isolate, mv_item.fallback_background_color));
builder.Set(
"fallbackTextColorRgba",
internal::RGBAColorToArray(isolate, mv_item.fallback_text_color));
}
return builder.Build();
}
......
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