Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(759)

Side by Side Diff: chrome/browser/android/manifest_icon_selector.cc

Issue 880203004: Break out manifest icon logic from ShortcutHelper (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Other patch landed Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/android/manifest_icon_selector.h"
6
7 #include <limits>
8
9 #include "base/strings/utf_string_conversions.h"
10 #include "content/public/browser/web_contents.h"
11 #include "net/base/mime_util.h"
12 #include "ui/gfx/screen.h"
13
14 using content::Manifest;
15
16 // static
17 bool ManifestIconSelector::IconSizesContainsPreferredSize(
18 const std::vector<gfx::Size>& sizes,
19 int preferred_icon_size_in_px) {
20 for (size_t i = 0; i < sizes.size(); ++i) {
21 if (sizes[i].height() != sizes[i].width())
22 continue;
23 if (sizes[i].width() == preferred_icon_size_in_px)
24 return true;
25 }
26
27 return false;
28 }
29
30 // static
31 bool ManifestIconSelector::IconSizesContainsAny(
32 const std::vector<gfx::Size>& sizes) {
33 for (size_t i = 0; i < sizes.size(); ++i) {
34 if (sizes[i].IsEmpty())
35 return true;
36 }
37
38 return false;
39 }
40
41 // static
42 GURL ManifestIconSelector::FindBestMatchingIcon(
43 const std::vector<Manifest::Icon>& icons,
44 float density,
45 int preferred_icon_size_in_px) {
46 GURL url;
47 int best_delta = std::numeric_limits<int>::min();
48
49 for (size_t i = 0; i < icons.size(); ++i) {
50 if (icons[i].density != density)
51 continue;
52
53 const std::vector<gfx::Size>& sizes = icons[i].sizes;
54 for (size_t j = 0; j < sizes.size(); ++j) {
55 if (sizes[j].height() != sizes[j].width())
56 continue;
57 int delta = sizes[j].width() - preferred_icon_size_in_px;
58 if (delta == 0)
59 return icons[i].src;
60 if (best_delta > 0 && delta < 0)
61 continue;
62 if ((best_delta > 0 && delta < best_delta) ||
63 (best_delta < 0 && delta > best_delta)) {
64 url = icons[i].src;
65 best_delta = delta;
66 }
67 }
68 }
69
70 return url;
71 }
72
73 // static
74 std::vector<Manifest::Icon> ManifestIconSelector::FilterIconsByType(
75 const std::vector<Manifest::Icon>& icons) {
76 std::vector<Manifest::Icon> result;
77
78 for (size_t i = 0; i < icons.size(); ++i) {
79 if (icons[i].type.is_null() ||
80 net::IsSupportedImageMimeType(
81 base::UTF16ToUTF8(icons[i].type.string()))) {
82 result.push_back(icons[i]);
83 }
84 }
85
86 return result;
87 }
88
89 // static
90 GURL ManifestIconSelector::FindBestMatchingIcon(
91 const std::vector<Manifest::Icon>& unfiltered_icons,
92 const float preferred_size_in_dp,
93 content::WebContents* web_contents) {
94 const float device_scale_factor =
95 gfx::Screen::GetScreenFor(web_contents->GetNativeView())->
96 GetPrimaryDisplay().device_scale_factor();
97 const float preferred_size_in_px =
98 preferred_size_in_dp * device_scale_factor;
99
100 GURL url;
101 std::vector<Manifest::Icon> icons = FilterIconsByType(unfiltered_icons);
102
103 // The first pass is to find the ideal icon. That icon is of the right size
104 // with the default density or the device's density.
105 for (size_t i = 0; i < icons.size(); ++i) {
106 if (icons[i].density == device_scale_factor &&
107 IconSizesContainsPreferredSize(icons[i].sizes, preferred_size_in_px)) {
108 return icons[i].src;
109 }
110
111 // If there is an icon with the right size but not the right density, keep
112 // it on the side and only use it if nothing better is found.
113 if (icons[i].density == Manifest::Icon::kDefaultDensity &&
114 IconSizesContainsPreferredSize(icons[i].sizes, preferred_size_in_px)) {
115 url = icons[i].src;
116 }
117 }
118
119 // The second pass is to find an icon with 'any'. The current device scale
120 // factor is preferred. Otherwise, the default scale factor is used.
121 for (size_t i = 0; i < icons.size(); ++i) {
122 if (icons[i].density == device_scale_factor &&
123 IconSizesContainsAny(icons[i].sizes)) {
124 return icons[i].src;
125 }
126
127 // If there is an icon with 'any' but not the right density, keep it on the
128 // side and only use it if nothing better is found.
129 if (icons[i].density == Manifest::Icon::kDefaultDensity &&
130 IconSizesContainsAny(icons[i].sizes)) {
131 url = icons[i].src;
132 }
133 }
134
135 // The last pass will try to find the best suitable icon for the device's
136 // scale factor. If none, another pass will be run using kDefaultDensity.
137 if (!url.is_valid())
138 url = FindBestMatchingIcon(icons,
139 device_scale_factor,
140 preferred_size_in_px);
141 if (!url.is_valid())
142 url = FindBestMatchingIcon(icons,
143 Manifest::Icon::kDefaultDensity,
144 preferred_size_in_px);
145
146 return url;
147 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698