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

Side by Side Diff: components/arc/intent_helper/activity_icon_loader.cc

Issue 2655233007: Get rid of RefCounted for ActivityIconLoader. (Closed)
Patch Set: address comments 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "components/arc/intent_helper/activity_icon_loader.h" 5 #include "components/arc/intent_helper/activity_icon_loader.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 8
9 #include <tuple> 9 #include <tuple>
10 #include <utility> 10 #include <utility>
11 11
12 #include "base/base64.h" 12 #include "base/base64.h"
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/memory/ptr_util.h" 14 #include "base/memory/ptr_util.h"
15 #include "base/memory/ref_counted.h"
15 #include "base/task_runner_util.h" 16 #include "base/task_runner_util.h"
16 #include "components/arc/arc_bridge_service.h" 17 #include "components/arc/arc_bridge_service.h"
17 #include "components/arc/arc_service_manager.h" 18 #include "components/arc/arc_service_manager.h"
19 #include "components/arc/arc_util.h"
18 #include "ui/base/layout.h" 20 #include "ui/base/layout.h"
19 #include "ui/gfx/image/image_skia.h" 21 #include "ui/gfx/image/image_skia.h"
20 #include "ui/gfx/image/image_skia_operations.h" 22 #include "ui/gfx/image/image_skia_operations.h"
21 23
22 namespace arc { 24 namespace arc {
25 namespace internal {
23 26
24 namespace { 27 namespace {
25 28
26 constexpr size_t kSmallIconSizeInDip = 16; 29 constexpr size_t kSmallIconSizeInDip = 16;
27 constexpr size_t kLargeIconSizeInDip = 20; 30 constexpr size_t kLargeIconSizeInDip = 20;
28 constexpr size_t kMaxIconSizeInPx = 200; 31 constexpr size_t kMaxIconSizeInPx = 200;
29 constexpr char kPngDataUrlPrefix[] = "data:image/png;base64,"; 32 constexpr char kPngDataUrlPrefix[] = "data:image/png;base64,";
30 33
31 ui::ScaleFactor GetSupportedScaleFactor() { 34 ui::ScaleFactor GetSupportedScaleFactor() {
32 std::vector<ui::ScaleFactor> scale_factors = ui::GetSupportedScaleFactors(); 35 std::vector<ui::ScaleFactor> scale_factors = ui::GetSupportedScaleFactors();
33 DCHECK(!scale_factors.empty()); 36 DCHECK(!scale_factors.empty());
34 return scale_factors.back(); 37 return scale_factors.back();
35 } 38 }
36 39
37 // Returns an instance for calling RequestActivityIcons(). 40 // Returns an instance for calling RequestActivityIcons().
38 mojom::IntentHelperInstance* GetInstanceForRequestActivityIcons( 41 mojom::IntentHelperInstance* GetInstanceForRequestActivityIcons(
39 ArcIntentHelperBridge::GetResult* out_error_code) { 42 ActivityIconLoader::GetResult* out_error_code) {
40 if (!ArcIntentHelperBridge::IsIntentHelperAvailable(out_error_code)) 43 auto* arc_service_manager = ArcServiceManager::Get();
44 if (!arc_service_manager) {
45 // TODO(hidehiko): IsArcAvailable() looks not the condition to be checked
46 // here, because ArcServiceManager instance is created regardless of ARC
47 // availability. This happens only before MessageLoop starts or after
48 // MessageLoop stops, practically.
49 // Also, returning FAILED_ARC_NOT_READY looks problematic at the moment,
50 // because ArcProcessTask::StartIconLoading accesses to
51 // ArcServiceManager::Get() return value, which can be nullptr.
52 if (!IsArcAvailable()) {
53 VLOG(2) << "ARC bridge is not supported.";
54 if (out_error_code) {
55 *out_error_code =
56 ActivityIconLoader::GetResult::FAILED_ARC_NOT_SUPPORTED;
57 }
58 } else {
59 VLOG(2) << "ARC bridge is not ready.";
60 if (out_error_code)
61 *out_error_code = ActivityIconLoader::GetResult::FAILED_ARC_NOT_READY;
62 }
41 return nullptr; 63 return nullptr;
42 auto* instance = ARC_GET_INSTANCE_FOR_METHOD(
43 ArcServiceManager::Get()->arc_bridge_service()->intent_helper(),
44 RequestActivityIcons);
45 if (!instance && out_error_code) {
46 *out_error_code =
47 ArcIntentHelperBridge::GetResult::FAILED_ARC_NOT_SUPPORTED;
48 } 64 }
65
66 auto* intent_helper_holder =
67 arc_service_manager->arc_bridge_service()->intent_helper();
68 if (!intent_helper_holder->has_instance()) {
69 VLOG(2) << "ARC intent helper instance is not ready.";
70 if (out_error_code)
71 *out_error_code = ActivityIconLoader::GetResult::FAILED_ARC_NOT_READY;
72 return nullptr;
73 }
74
75 auto* instance = ARC_GET_INSTANCE_FOR_METHOD(intent_helper_holder,
76 RequestActivityIcons);
77 if (!instance && out_error_code)
78 *out_error_code = ActivityIconLoader::GetResult::FAILED_ARC_NOT_SUPPORTED;
49 return instance; 79 return instance;
50 } 80 }
51 81
82 std::unique_ptr<ActivityIconLoader::ActivityToIconsMap> ResizeAndEncodeIcons(
83 std::vector<mojom::ActivityIconPtr> icons) {
84 auto result = base::MakeUnique<ActivityIconLoader::ActivityToIconsMap>();
85 for (size_t i = 0; i < icons.size(); ++i) {
86 static const size_t kBytesPerPixel = 4;
87 const mojom::ActivityIconPtr& icon = icons.at(i);
88 if (icon->width > kMaxIconSizeInPx || icon->height > kMaxIconSizeInPx ||
89 icon->width == 0 || icon->height == 0 ||
90 icon->icon.size() != (icon->width * icon->height * kBytesPerPixel)) {
91 continue;
92 }
93
94 SkBitmap bitmap;
95 bitmap.allocPixels(SkImageInfo::MakeN32Premul(icon->width, icon->height));
96 if (!bitmap.getPixels())
97 continue;
98 DCHECK_GE(bitmap.getSafeSize(), icon->icon.size());
99 memcpy(bitmap.getPixels(), &icon->icon.front(), icon->icon.size());
100
101 gfx::ImageSkia original(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
102
103 // Resize the original icon to the sizes intent_helper needs.
104 gfx::ImageSkia icon_large(gfx::ImageSkiaOperations::CreateResizedImage(
105 original, skia::ImageOperations::RESIZE_BEST,
106 gfx::Size(kLargeIconSizeInDip, kLargeIconSizeInDip)));
107 gfx::ImageSkia icon_small(gfx::ImageSkiaOperations::CreateResizedImage(
108 original, skia::ImageOperations::RESIZE_BEST,
109 gfx::Size(kSmallIconSizeInDip, kSmallIconSizeInDip)));
110 gfx::Image icon16(icon_small);
111 gfx::Image icon20(icon_large);
112
113 // Encode the icon as PNG data, and then as data: URL.
114 scoped_refptr<base::RefCountedMemory> img = icon16.As1xPNGBytes();
115 if (!img)
116 continue;
117 std::string encoded;
118 base::Base64Encode(base::StringPiece(img->front_as<char>(), img->size()),
119 &encoded);
120 scoped_refptr<base::RefCountedData<GURL>> dataurl(
121 new base::RefCountedData<GURL>(GURL(kPngDataUrlPrefix + encoded)));
122
123 const std::string activity_name = icon->activity->activity_name.has_value()
124 ? (*icon->activity->activity_name)
125 : std::string();
126 result->insert(
127 std::make_pair(ActivityIconLoader::ActivityName(
128 icon->activity->package_name, activity_name),
129 ActivityIconLoader::Icons(icon16, icon20, dataurl)));
130 }
131
132 return result;
133 }
134
52 } // namespace 135 } // namespace
53 136
54 ActivityIconLoader::Icons::Icons( 137 ActivityIconLoader::Icons::Icons(
55 const gfx::Image& icon16, 138 const gfx::Image& icon16,
56 const gfx::Image& icon20, 139 const gfx::Image& icon20,
57 const scoped_refptr<base::RefCountedData<GURL>>& icon16_dataurl) 140 const scoped_refptr<base::RefCountedData<GURL>>& icon16_dataurl)
58 : icon16(icon16), icon20(icon20), icon16_dataurl(icon16_dataurl) {} 141 : icon16(icon16), icon20(icon20), icon16_dataurl(icon16_dataurl) {}
59 142
60 ActivityIconLoader::Icons::Icons(const Icons& other) = default; 143 ActivityIconLoader::Icons::Icons(const Icons& other) = default;
61 144
62 ActivityIconLoader::Icons::~Icons() = default; 145 ActivityIconLoader::Icons::~Icons() = default;
63 146
64 ActivityIconLoader::ActivityName::ActivityName(const std::string& package_name, 147 ActivityIconLoader::ActivityName::ActivityName(const std::string& package_name,
65 const std::string& activity_name) 148 const std::string& activity_name)
66 : package_name(package_name), activity_name(activity_name) {} 149 : package_name(package_name), activity_name(activity_name) {}
67 150
68 bool ActivityIconLoader::ActivityName::operator<( 151 bool ActivityIconLoader::ActivityName::operator<(
69 const ActivityName& other) const { 152 const ActivityName& other) const {
70 return std::tie(package_name, activity_name) < 153 return std::tie(package_name, activity_name) <
71 std::tie(other.package_name, other.activity_name); 154 std::tie(other.package_name, other.activity_name);
72 } 155 }
73 156
74 ActivityIconLoader::ActivityIconLoader() 157 ActivityIconLoader::ActivityIconLoader()
75 : scale_factor_(GetSupportedScaleFactor()) {} 158 : scale_factor_(GetSupportedScaleFactor()), weak_ptr_factory_(this) {}
76 159
77 ActivityIconLoader::~ActivityIconLoader() {} 160 ActivityIconLoader::~ActivityIconLoader() = default;
78 161
79 void ActivityIconLoader::InvalidateIcons(const std::string& package_name) { 162 void ActivityIconLoader::InvalidateIcons(const std::string& package_name) {
80 DCHECK(thread_checker_.CalledOnValidThread()); 163 DCHECK(thread_checker_.CalledOnValidThread());
81 for (auto it = cached_icons_.begin(); it != cached_icons_.end();) { 164 for (auto it = cached_icons_.begin(); it != cached_icons_.end();) {
82 if (it->first.package_name == package_name) 165 if (it->first.package_name == package_name)
83 it = cached_icons_.erase(it); 166 it = cached_icons_.erase(it);
84 else 167 else
85 ++it; 168 ++it;
86 } 169 }
87 } 170 }
(...skipping 16 matching lines...) Expand all
104 result->insert(std::make_pair(activity, it->second)); 187 result->insert(std::make_pair(activity, it->second));
105 } 188 }
106 } 189 }
107 190
108 if (activities_to_fetch.empty()) { 191 if (activities_to_fetch.empty()) {
109 // If there's nothing to fetch, run the callback now. 192 // If there's nothing to fetch, run the callback now.
110 cb.Run(std::move(result)); 193 cb.Run(std::move(result));
111 return GetResult::SUCCEEDED_SYNC; 194 return GetResult::SUCCEEDED_SYNC;
112 } 195 }
113 196
114 ArcIntentHelperBridge::GetResult error_code; 197 GetResult error_code;
115 auto* instance = GetInstanceForRequestActivityIcons(&error_code); 198 auto* instance = GetInstanceForRequestActivityIcons(&error_code);
116 if (!instance) { 199 if (!instance) {
117 // The mojo channel is not yet ready (or not supported at all). Run the 200 // The mojo channel is not yet ready (or not supported at all). Run the
118 // callback with |result| that could be empty. 201 // callback with |result| that could be empty.
119 cb.Run(std::move(result)); 202 cb.Run(std::move(result));
120 switch (error_code) { 203 return error_code;
121 case ArcIntentHelperBridge::GetResult::FAILED_ARC_NOT_READY:
122 return GetResult(GetResult::FAILED_ARC_NOT_READY);
123 case ArcIntentHelperBridge::GetResult::FAILED_ARC_NOT_SUPPORTED:
124 return GetResult(GetResult::FAILED_ARC_NOT_SUPPORTED);
125 }
126 NOTREACHED();
127 } 204 }
128 205
129 // Fetch icons from ARC. 206 // Fetch icons from ARC.
130 instance->RequestActivityIcons( 207 instance->RequestActivityIcons(
131 std::move(activities_to_fetch), mojom::ScaleFactor(scale_factor_), 208 std::move(activities_to_fetch), mojom::ScaleFactor(scale_factor_),
132 base::Bind(&ActivityIconLoader::OnIconsReady, this, base::Passed(&result), 209 base::Bind(&ActivityIconLoader::OnIconsReady,
133 cb)); 210 weak_ptr_factory_.GetWeakPtr(), base::Passed(&result), cb));
134 return GetResult::SUCCEEDED_ASYNC; 211 return GetResult::SUCCEEDED_ASYNC;
135 } 212 }
136 213
137 void ActivityIconLoader::OnIconsResizedForTesting( 214 void ActivityIconLoader::OnIconsResizedForTesting(
138 const OnIconsReadyCallback& cb, 215 const OnIconsReadyCallback& cb,
139 std::unique_ptr<ActivityToIconsMap> result) { 216 std::unique_ptr<ActivityToIconsMap> result) {
140 OnIconsResized(base::MakeUnique<ActivityToIconsMap>(), cb, std::move(result)); 217 OnIconsResized(base::MakeUnique<ActivityToIconsMap>(), cb, std::move(result));
141 } 218 }
142 219
143 void ActivityIconLoader::AddCacheEntryForTesting(const ActivityName& activity) { 220 void ActivityIconLoader::AddCacheEntryForTesting(const ActivityName& activity) {
(...skipping 15 matching lines...) Expand all
159 } 236 }
160 237
161 void ActivityIconLoader::OnIconsReady( 238 void ActivityIconLoader::OnIconsReady(
162 std::unique_ptr<ActivityToIconsMap> cached_result, 239 std::unique_ptr<ActivityToIconsMap> cached_result,
163 const OnIconsReadyCallback& cb, 240 const OnIconsReadyCallback& cb,
164 std::vector<mojom::ActivityIconPtr> icons) { 241 std::vector<mojom::ActivityIconPtr> icons) {
165 DCHECK(thread_checker_.CalledOnValidThread()); 242 DCHECK(thread_checker_.CalledOnValidThread());
166 ArcServiceManager* manager = ArcServiceManager::Get(); 243 ArcServiceManager* manager = ArcServiceManager::Get();
167 base::PostTaskAndReplyWithResult( 244 base::PostTaskAndReplyWithResult(
168 manager->blocking_task_runner().get(), FROM_HERE, 245 manager->blocking_task_runner().get(), FROM_HERE,
169 base::Bind(&ActivityIconLoader::ResizeAndEncodeIcons, 246 base::Bind(&ResizeAndEncodeIcons, base::Passed(&icons)),
170 base::Passed(&icons)), 247 base::Bind(&ActivityIconLoader::OnIconsResized,
171 base::Bind(&ActivityIconLoader::OnIconsResized, this, 248 weak_ptr_factory_.GetWeakPtr(), base::Passed(&cached_result),
172 base::Passed(&cached_result), cb)); 249 cb));
173 }
174
175 // static
176 std::unique_ptr<ActivityIconLoader::ActivityToIconsMap>
177 ActivityIconLoader::ResizeAndEncodeIcons(
178 std::vector<mojom::ActivityIconPtr> icons) {
179 std::unique_ptr<ActivityToIconsMap> result(new ActivityToIconsMap);
180
181 for (size_t i = 0; i < icons.size(); ++i) {
182 static const size_t kBytesPerPixel = 4;
183 const mojom::ActivityIconPtr& icon = icons.at(i);
184 if (icon->width > kMaxIconSizeInPx || icon->height > kMaxIconSizeInPx ||
185 icon->width == 0 || icon->height == 0 ||
186 icon->icon.size() != (icon->width * icon->height * kBytesPerPixel)) {
187 continue;
188 }
189
190 SkBitmap bitmap;
191 bitmap.allocPixels(SkImageInfo::MakeN32Premul(icon->width, icon->height));
192 if (!bitmap.getPixels())
193 continue;
194 DCHECK_GE(bitmap.getSafeSize(), icon->icon.size());
195 memcpy(bitmap.getPixels(), &icon->icon.front(), icon->icon.size());
196
197 gfx::ImageSkia original(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
198
199 // Resize the original icon to the sizes intent_helper needs.
200 gfx::ImageSkia icon_large(gfx::ImageSkiaOperations::CreateResizedImage(
201 original, skia::ImageOperations::RESIZE_BEST,
202 gfx::Size(kLargeIconSizeInDip, kLargeIconSizeInDip)));
203 gfx::ImageSkia icon_small(gfx::ImageSkiaOperations::CreateResizedImage(
204 original, skia::ImageOperations::RESIZE_BEST,
205 gfx::Size(kSmallIconSizeInDip, kSmallIconSizeInDip)));
206 gfx::Image icon16(icon_small);
207 gfx::Image icon20(icon_large);
208
209 // Encode the icon as PNG data, and then as data: URL.
210 scoped_refptr<base::RefCountedMemory> img = icon16.As1xPNGBytes();
211 if (!img)
212 continue;
213 std::string encoded;
214 base::Base64Encode(base::StringPiece(img->front_as<char>(), img->size()),
215 &encoded);
216 scoped_refptr<base::RefCountedData<GURL>> dataurl(
217 new base::RefCountedData<GURL>(GURL(kPngDataUrlPrefix + encoded)));
218
219 const std::string activity_name = icon->activity->activity_name.has_value()
220 ? (*icon->activity->activity_name)
221 : std::string();
222 result->insert(std::make_pair(
223 ActivityName(icon->activity->package_name, activity_name),
224 Icons(icon16, icon20, dataurl)));
225 }
226
227 return result;
228 } 250 }
229 251
230 void ActivityIconLoader::OnIconsResized( 252 void ActivityIconLoader::OnIconsResized(
231 std::unique_ptr<ActivityToIconsMap> cached_result, 253 std::unique_ptr<ActivityToIconsMap> cached_result,
232 const OnIconsReadyCallback& cb, 254 const OnIconsReadyCallback& cb,
233 std::unique_ptr<ActivityToIconsMap> result) { 255 std::unique_ptr<ActivityToIconsMap> result) {
234 DCHECK(thread_checker_.CalledOnValidThread()); 256 DCHECK(thread_checker_.CalledOnValidThread());
235 // Update |cached_icons_|. 257 // Update |cached_icons_|.
236 for (const auto& kv : *result) { 258 for (const auto& kv : *result) {
237 cached_icons_.erase(kv.first); 259 cached_icons_.erase(kv.first);
238 cached_icons_.insert(std::make_pair(kv.first, kv.second)); 260 cached_icons_.insert(std::make_pair(kv.first, kv.second));
239 } 261 }
240 262
241 // Merge the results that were obtained from cache before doing IPC. 263 // Merge the results that were obtained from cache before doing IPC.
242 result->insert(cached_result->begin(), cached_result->end()); 264 result->insert(cached_result->begin(), cached_result->end());
243 cb.Run(std::move(result)); 265 cb.Run(std::move(result));
244 } 266 }
245 267
268 } // namespace internal
246 } // namespace arc 269 } // namespace arc
OLDNEW
« no previous file with comments | « components/arc/intent_helper/activity_icon_loader.h ('k') | components/arc/intent_helper/activity_icon_loader_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698