Commit 19a61abe authored by John Lee's avatar John Lee Committed by Commit Bot

Tab Strip WebUI: Use favicon from TabRendererData

Previously, the tab strip was using favicon by using chrome://favicon,
which depends on history and consequently did not work in incognito
mode for sites the user did not visit in a normal window.

Bug: 992972
Change-Id: I6407353c649876fe78c4ffb2425ebcd761e5d0fe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1850965
Commit-Queue: John Lee <johntlee@chromium.org>
Reviewed-by: default avatarCollin Baker <collinbaker@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704909}
parent d5857f58
...@@ -79,7 +79,7 @@ export class TabElement extends CustomElement { ...@@ -79,7 +79,7 @@ export class TabElement extends CustomElement {
if (tab.favIconUrl) { if (tab.favIconUrl) {
if (!this.tab_ || this.tab_.favIconUrl !== tab.favIconUrl) { if (!this.tab_ || this.tab_.favIconUrl !== tab.favIconUrl) {
this.faviconEl_.style.backgroundImage = getFavicon(tab.favIconUrl); this.faviconEl_.style.backgroundImage = `url(${tab.favIconUrl})`;
} }
} else { } else {
if (tab.networkState === TabNetworkState.NONE || if (tab.networkState === TabNetworkState.NONE ||
......
...@@ -68,6 +68,28 @@ class BufferWStream : public SkWStream { ...@@ -68,6 +68,28 @@ class BufferWStream : public SkWStream {
std::vector<unsigned char> result_; std::vector<unsigned char> result_;
}; };
std::string EncodeImage(gfx::ImageSkia image,
SkEncodedImageFormat format,
float scale_factor) {
const SkBitmap& bitmap = image.GetRepresentation(scale_factor).GetBitmap();
BufferWStream stream;
const bool encoding_succeeded = SkEncodeImage(&stream, bitmap, format, 100);
DCHECK(encoding_succeeded);
const std::vector<unsigned char> image_data = stream.GetBuffer();
std::string mime_subtype;
if (format == SkEncodedImageFormat::kJPEG) {
mime_subtype = "jpeg";
} else if (format == SkEncodedImageFormat::kPNG) {
mime_subtype = "png";
} else {
NOTREACHED();
}
return "data:image/" + mime_subtype + ";base64," +
base::Base64Encode(base::as_bytes(base::make_span(image_data)));
}
class WebUITabContextMenu : public ui::SimpleMenuModel::Delegate, class WebUITabContextMenu : public ui::SimpleMenuModel::Delegate,
public TabMenuModel { public TabMenuModel {
public: public:
...@@ -195,18 +217,19 @@ class TabStripUIHandler : public content::WebUIMessageHandler, ...@@ -195,18 +217,19 @@ class TabStripUIHandler : public content::WebUIMessageHandler,
tab_data.SetInteger("id", extensions::ExtensionTabUtil::GetTabId(contents)); tab_data.SetInteger("id", extensions::ExtensionTabUtil::GetTabId(contents));
tab_data.SetInteger("index", index); tab_data.SetInteger("index", index);
// TODO(johntlee): Replace with favicon from TabRendererData
content::NavigationEntry* visible_entry =
contents->GetController().GetVisibleEntry();
if (visible_entry && visible_entry->GetFavicon().valid) {
tab_data.SetString("favIconUrl", visible_entry->GetFavicon().url.spec());
}
TabRendererData tab_renderer_data = TabRendererData tab_renderer_data =
TabRendererData::FromTabInModel(browser_->tab_strip_model(), index); TabRendererData::FromTabInModel(browser_->tab_strip_model(), index);
tab_data.SetBoolean("pinned", tab_renderer_data.pinned); tab_data.SetBoolean("pinned", tab_renderer_data.pinned);
tab_data.SetString("title", tab_renderer_data.title); tab_data.SetString("title", tab_renderer_data.title);
tab_data.SetString("url", tab_renderer_data.visible_url.GetContent()); tab_data.SetString("url", tab_renderer_data.visible_url.GetContent());
if (!tab_renderer_data.favicon.isNull()) {
tab_data.SetString(
"favIconUrl",
EncodeImage(tab_renderer_data.favicon, SkEncodedImageFormat::kPNG,
web_ui()->GetDeviceScaleFactor()));
}
tab_data.SetInteger("networkState", tab_data.SetInteger("networkState",
static_cast<int>(tab_renderer_data.network_state)); static_cast<int>(tab_renderer_data.network_state));
tab_data.SetBoolean("shouldHideThrobber", tab_data.SetBoolean("shouldHideThrobber",
...@@ -327,14 +350,6 @@ class TabStripUIHandler : public content::WebUIMessageHandler, ...@@ -327,14 +350,6 @@ class TabStripUIHandler : public content::WebUIMessageHandler,
// Callback passed to |thumbnail_tracker_|. Called when a tab's thumbnail // Callback passed to |thumbnail_tracker_|. Called when a tab's thumbnail
// changes, or when we start watching the tab. // changes, or when we start watching the tab.
void HandleThumbnailUpdate(content::WebContents* tab, gfx::ImageSkia image) { void HandleThumbnailUpdate(content::WebContents* tab, gfx::ImageSkia image) {
const SkBitmap& bitmap =
image.GetRepresentation(web_ui()->GetDeviceScaleFactor()).GetBitmap();
BufferWStream stream;
const bool encoding_succeeded =
SkEncodeImage(&stream, bitmap, SkEncodedImageFormat::kJPEG, 100);
DCHECK(encoding_succeeded);
const std::vector<unsigned char> image_data = stream.GetBuffer();
// Send base-64 encoded image to JS side. // Send base-64 encoded image to JS side.
// //
// TODO(crbug.com/991393): streamline the process from tab capture to // TODO(crbug.com/991393): streamline the process from tab capture to
...@@ -346,9 +361,8 @@ class TabStripUIHandler : public content::WebUIMessageHandler, ...@@ -346,9 +361,8 @@ class TabStripUIHandler : public content::WebUIMessageHandler,
// copies of essentially the same image, and it is de-encoded and re-encoded // copies of essentially the same image, and it is de-encoded and re-encoded
// to the same format. We can reduce the number of copies and avoid the // to the same format. We can reduce the number of copies and avoid the
// redundant encoding. // redundant encoding.
std::string encoded_image = std::string encoded_image = EncodeImage(image, SkEncodedImageFormat::kJPEG,
base::Base64Encode(base::as_bytes(base::make_span(image_data))); web_ui()->GetDeviceScaleFactor());
encoded_image = "data:image/jpeg;base64," + encoded_image;
const int tab_id = extensions::ExtensionTabUtil::GetTabId(tab); const int tab_id = extensions::ExtensionTabUtil::GetTabId(tab);
FireWebUIListener("tab-thumbnail-updated", base::Value(tab_id), FireWebUIListener("tab-thumbnail-updated", base::Value(tab_id),
......
...@@ -108,11 +108,11 @@ suite('Tab', function() { ...@@ -108,11 +108,11 @@ suite('Tab', function() {
}); });
test('sets the favicon to the favicon URL', () => { test('sets the favicon to the favicon URL', () => {
const expectedFaviconUrl = 'http://google.com/favicon.ico'; const expectedFaviconUrl = 'data:mock-favicon';
tabElement.tab = Object.assign({}, tab, {favIconUrl: expectedFaviconUrl}); tabElement.tab = Object.assign({}, tab, {favIconUrl: expectedFaviconUrl});
const faviconElement = tabElement.shadowRoot.querySelector('#favicon'); const faviconElement = tabElement.shadowRoot.querySelector('#favicon');
assertEquals( assertEquals(
faviconElement.style.backgroundImage, getFavicon(expectedFaviconUrl)); faviconElement.style.backgroundImage, `url("${expectedFaviconUrl}")`);
}); });
test('sets the favicon to the page URL if favicon URL does not exist', () => { test('sets the favicon to the page URL if favicon URL does not exist', () => {
......
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