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

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

Issue 2662103002: Refactor ManifestIconSelector and update it for Manifest.icon.purpose (Closed)
Patch Set: InstallableManager not updated Created 3 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/manifest/manifest_icon_selector.h" 5 #include "chrome/browser/manifest/manifest_icon_selector.h"
6 6
7 #include <stddef.h>
8
9 #include <algorithm>
10 #include <cmath>
11 #include <limits> 7 #include <limits>
12 8
9 #include "base/stl_util.h"
13 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
14 #include "components/mime_util/mime_util.h" 11 #include "components/mime_util/mime_util.h"
15 #include "content/public/browser/web_contents.h"
16 12
17 using content::Manifest; 13 // static
14 GURL ManifestIconSelector::FindBestMatchingIcon(
15 const std::vector<content::Manifest::Icon>& icons,
16 int ideal_icon_size_in_px,
17 int minimum_icon_size_in_px,
18 content::Manifest::Icon::IconPurpose purpose) {
19 int exact_size_match_index = -1;
20 int latest_size_any_index = -1;
21 int closest_size_match_index = -1;
22 int best_delta_in_size = std::numeric_limits<int>::min();
18 23
19 ManifestIconSelector::ManifestIconSelector(int ideal_icon_size_in_px, 24 for (size_t i = 0; i < icons.size() && exact_size_match_index == -1; ++i) {
dominickn 2017/01/31 01:52:17 The only time exact_size_match_index is set is imm
F 2017/01/31 16:52:59 Done. Thanks!
20 int minimum_icon_size_in_px) 25 const auto& icon = icons[i];
21 : ideal_icon_size_in_px_(ideal_icon_size_in_px),
22 minimum_icon_size_in_px_(minimum_icon_size_in_px) {
23 }
24 26
25 bool ManifestIconSelector::IconSizesContainsPreferredSize( 27 // Check for supported image MIME types.
26 const std::vector<gfx::Size>& sizes) const { 28 if (!(icon.type.empty() ||
27 for (size_t i = 0; i < sizes.size(); ++i) { 29 mime_util::IsSupportedImageMimeType(base::UTF16ToUTF8(icon.type)))) {
28 if (sizes[i].height() != sizes[i].width())
29 continue; 30 continue;
30 if (sizes[i].width() == ideal_icon_size_in_px_) 31 }
31 return true;
32 }
33 32
34 return false; 33 // Check for icon purpose.
35 } 34 if (!base::ContainsValue(icon.purpose, purpose))
35 continue;
36 36
37 bool ManifestIconSelector::IconSizesContainsBiggerThanMinimumSize( 37 // Check for size constraints.
38 const std::vector<gfx::Size>& sizes) const { 38 for (const auto& size : icon.sizes) {
39 for (size_t i = 0; i < sizes.size(); ++i) { 39 // Check for size "any".
dominickn 2017/01/31 01:52:17 Nit: // Check for size "any". Return this icon if
F 2017/01/31 16:52:59 Done.
40 if (sizes[i].height() != sizes[i].width()) 40 if (size.IsEmpty()) {
41 continue; 41 latest_size_any_index = i;
42 if (sizes[i].width() >= minimum_icon_size_in_px_) 42 continue;
43 return true; 43 }
44 }
45 return false;
46 }
47 44
48 int ManifestIconSelector::FindClosestIconToIdealSize( 45 // Check for squareness.
49 const std::vector<content::Manifest::Icon>& icons) const { 46 if (size.width() != size.height())
50 int best_index = -1; 47 continue;
51 int best_delta = std::numeric_limits<int>::min();
52 48
53 for (size_t i = 0; i < icons.size(); ++i) { 49 // Check for minimum size.
54 const std::vector<gfx::Size>& sizes = icons[i].sizes; 50 if (size.width() < minimum_icon_size_in_px)
55 for (size_t j = 0; j < sizes.size(); ++j) {
56 if (sizes[j].height() != sizes[j].width())
57 continue; 51 continue;
58 int delta = sizes[j].width() - ideal_icon_size_in_px_; 52
59 if (delta == 0) 53 // Check for ideal size.
60 return i; 54 if (size.width() == ideal_icon_size_in_px) {
61 if (best_delta > 0 && delta < 0) 55 exact_size_match_index = i;
56 break;
57 }
58
59 // Check for closest match.
60 int delta = size.width() - ideal_icon_size_in_px;
61
62 // Smallest icon larger than ideal size has priority over largest icon
63 // smaller than ideal size.
64 if (best_delta_in_size > 0 && delta < 0)
62 continue; 65 continue;
63 if ((best_delta > 0 && delta < best_delta) || 66
64 (best_delta < 0 && delta > best_delta)) { 67 if ((best_delta_in_size > 0 && delta < best_delta_in_size) ||
65 best_index = i; 68 (best_delta_in_size < 0 && delta > best_delta_in_size)) {
66 best_delta = delta; 69 closest_size_match_index = i;
70 best_delta_in_size = delta;
67 } 71 }
68 } 72 }
69 } 73 }
70 74
71 return best_index; 75 // Icon with exact matching size has priority over icon with size "any", which
76 // has priority over icon with closest matching size.
77 if (exact_size_match_index != -1)
78 return icons[exact_size_match_index].src;
79 else if (latest_size_any_index != -1)
80 return icons[latest_size_any_index].src;
81 else if (closest_size_match_index != -1)
82 return icons[closest_size_match_index].src;
83 else
84 return GURL();
72 } 85 }
73
74 int ManifestIconSelector::FindBestMatchingIcon(
75 const std::vector<content::Manifest::Icon>& icons) const {
76 int best_index = -1;
77
78 // The first pass is to find the ideal icon - one with the exact right size.
79 for (size_t i = 0; i < icons.size(); ++i) {
80 if (IconSizesContainsPreferredSize(icons[i].sizes))
81 return i;
82
83 // If there is an icon size 'any', keep it on the side and only use it if
84 // nothing better is found.
85 if (IconSizesContainsAny(icons[i].sizes))
86 best_index = i;
87 }
88 if (best_index != -1)
89 return best_index;
90
91 // The last pass will try to find the smallest icon larger than the ideal
92 // size, or the largest icon smaller than the ideal size.
93 best_index = FindClosestIconToIdealSize(icons);
94
95 if (best_index != -1 &&
96 IconSizesContainsBiggerThanMinimumSize(icons[best_index].sizes))
97 return best_index;
98
99 return -1;
100 }
101
102
103 // static
104 bool ManifestIconSelector::IconSizesContainsAny(
105 const std::vector<gfx::Size>& sizes) {
106 for (size_t i = 0; i < sizes.size(); ++i) {
107 if (sizes[i].IsEmpty())
108 return true;
109 }
110 return false;
111 }
112
113 // static
114 std::vector<Manifest::Icon> ManifestIconSelector::FilterIconsByType(
115 const std::vector<content::Manifest::Icon>& icons) {
116 std::vector<Manifest::Icon> result;
117
118 for (size_t i = 0; i < icons.size(); ++i) {
119 if (icons[i].type.empty() ||
120 mime_util::IsSupportedImageMimeType(base::UTF16ToUTF8(icons[i].type))) {
121 result.push_back(icons[i]);
122 }
123 }
124
125 return result;
126 }
127
128 // static
129 GURL ManifestIconSelector::FindBestMatchingIcon(
130 const std::vector<Manifest::Icon>& unfiltered_icons,
131 const int ideal_icon_size_in_px,
132 const int minimum_icon_size_in_px) {
133 DCHECK(minimum_icon_size_in_px <= ideal_icon_size_in_px);
134
135 std::vector<Manifest::Icon> icons =
136 ManifestIconSelector::FilterIconsByType(unfiltered_icons);
137
138 ManifestIconSelector selector(ideal_icon_size_in_px,
139 minimum_icon_size_in_px);
140 int index = selector.FindBestMatchingIcon(icons);
141 if (index == -1)
142 return GURL();
143 return icons[index].src;
144 }
OLDNEW
« no previous file with comments | « chrome/browser/manifest/manifest_icon_selector.h ('k') | chrome/browser/manifest/manifest_icon_selector_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698