summaryrefslogtreecommitdiff
path: root/chromium/ui/webui/resources/js/icon.js
blob: 0d2c74000c8a0c120c0b48744ec12266a9c89cd1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// 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<number>} 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,
  };
});