// Copyright 2016 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 {isChromeOS, isIOS, isLinux, isMac, isWindows} from './cr.m.js'; cr.define('cr.icon', function() { /** * @return {!Array} The scale factors supported by this platform for * webui resources. */ function getSupportedScaleFactors() { const supportedScaleFactors = []; if (!cr.isIOS) { // This matches the code in ResourceBundle::InitSharedInstance() that // supports SCALE_FACTOR_100P on all non-iOS platforms. supportedScaleFactors.push(1); } if (cr.isMac || cr.isChromeOS || cr.isWindows || cr.isLinux) { // All desktop platforms support zooming which also updates the renderer's // device scale factors (a.k.a devicePixelRatio), and these platforms have // high DPI assets for 2x. Let the renderer pick the closest image for // the current device scale factor. supportedScaleFactors.push(2); } else { // For other platforms that use fixed device scale factor, use // the window's device pixel ratio. // TODO(oshima): Investigate corresponding to // ResourceBundle::InitSharedInstance() more closely. supportedScaleFactors.push(window.devicePixelRatio); } return supportedScaleFactors; } /** * Generates a CSS url string. * @param {string} s The URL to generate the CSS url for. * @return {string} The CSS url string. */ /* #export */ function getUrlForCss(s) { // http://www.w3.org/TR/css3-values/#uris // Parentheses, commas, whitespace characters, single quotes (') and double // quotes (") appearing in a URI must be escaped with a backslash const s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1'); return `url("${s2}")`; } /** * A URL for the filetype icon for |filePath|. OS and theme dependent. * @param {string} filePath * @return {string} */ /* #export */ function getFileIconUrl(filePath) { const url = new URL('chrome://fileicon/'); url.searchParams.set('path', filePath); url.searchParams.set('scale', window.devicePixelRatio + 'x'); return url.toString(); } /** * Generates a CSS -webkit-image-set for a chrome:// url. * An entry in the image set is added for each of getSupportedScaleFactors(). * The scale-factor-specific url is generated by replacing the first instance * of 'scalefactor' in |path| with the numeric scale factor. * * @param {string} path The URL to generate an image set for. * 'scalefactor' should be a substring of |path|. * @return {string} The CSS -webkit-image-set. */ function getImageSet(path) { const supportedScaleFactors = getSupportedScaleFactors(); const replaceStartIndex = path.indexOf('SCALEFACTOR'); if (replaceStartIndex < 0) { return getUrlForCss(path); } let s = ''; for (let i = 0; i < supportedScaleFactors.length; ++i) { const scaleFactor = supportedScaleFactors[i]; const pathWithScaleFactor = path.substr(0, replaceStartIndex) + scaleFactor + path.substr(replaceStartIndex + 'scalefactor'.length); s += getUrlForCss(pathWithScaleFactor) + ' ' + scaleFactor + 'x'; if (i !== supportedScaleFactors.length - 1) { s += ', '; } } return '-webkit-image-set(' + s + ')'; } /** * Returns the URL of the image, or an image set of URLs for the provided * path. Resources in chrome://theme have multiple supported scale factors. * * @param {string} path The path of the image. * @return {string} The url, or an image set of URLs. */ /* #export */ function getImage(path) { const chromeThemePath = 'chrome://theme'; const isChromeThemeUrl = (path.slice(0, chromeThemePath.length) === chromeThemePath); return isChromeThemeUrl ? getImageSet(path + '@SCALEFACTORx') : getUrlForCss(path); } function getBaseFaviconUrl() { const faviconUrl = new URL('chrome://favicon2/'); faviconUrl.searchParams.set('size', '16'); faviconUrl.searchParams.set('scale_factor', 'SCALEFACTORx'); return faviconUrl; } /** * Creates a CSS -webkit-image-set for a favicon. * * @param {string} url URL of the favicon * @return {string} -webkit-image-set for the favicon */ /* #export */ function getFavicon(url) { const faviconUrl = getBaseFaviconUrl(); faviconUrl.searchParams.set('icon_url', url); return getImageSet(faviconUrl.toString()); } /** * Creates a CSS -webkit-image-set for a favicon request based on a page URL. * * @param {string} url URL of the original page * @param {boolean} isSyncedUrlForHistoryUi Should be set to true only if the * caller is an UI aimed at displaying user history, and the requested url * is known to be present in Chrome sync data. * @param {string} remoteIconUrlForUma In case the entry is contained in * sync data, we can pass the associated icon url. * * @return {string} -webkit-image-set for the favicon. */ /* #export */ function getFaviconForPageURL( url, isSyncedUrlForHistoryUi, remoteIconUrlForUma = '') { // Note: URL param keys used below must match those in the description of // chrome://favicon2 format in components/favicon_base/favicon_url_parser.h. const faviconUrl = getBaseFaviconUrl(); faviconUrl.searchParams.set('page_url', url); // TODO(dbeam): use the presence of 'allow_google_server_fallback' to // indicate true, otherwise false. const fallback = isSyncedUrlForHistoryUi ? '1' : '0'; faviconUrl.searchParams.set('allow_google_server_fallback', fallback); if (isSyncedUrlForHistoryUi) { faviconUrl.searchParams.set('icon_url', remoteIconUrlForUma); } return getImageSet(faviconUrl.toString()); } // #cr_define_end return { getFavicon: getFavicon, getFaviconForPageURL: getFaviconForPageURL, getFileIconUrl: getFileIconUrl, getImage: getImage, getUrlForCss: getUrlForCss, }; });