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

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

Issue 2655233007: Get rid of RefCounted for ActivityIconLoader. (Closed)
Patch Set: put ActivityIconLoader internal namespace 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/command_line.h"
14 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
16 #include "base/memory/ref_counted.h"
15 #include "base/task_runner_util.h" 17 #include "base/task_runner_util.h"
16 #include "components/arc/arc_bridge_service.h" 18 #include "components/arc/arc_bridge_service.h"
17 #include "components/arc/arc_service_manager.h" 19 #include "components/arc/arc_service_manager.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 if (!ArcBridgeService::GetEnabled(base::CommandLine::ForCurrentProcess())) {
46 VLOG(2) << "ARC bridge is not supported.";
47 if (out_error_code) {
48 *out_error_code =
49 ActivityIconLoader::GetResult::FAILED_ARC_NOT_SUPPORTED;
50 }
51 } else {
52 VLOG(2) << "ARC bridge is not ready.";
53 if (out_error_code)
54 *out_error_code = ActivityIconLoader::GetResult::FAILED_ARC_NOT_READY;
55 }
41 return nullptr; 56 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 } 57 }
58
59 auto* intent_helper_holder =
60 arc_service_manager->arc_bridge_service()->intent_helper();
61 if (!intent_helper_holder->has_instance()) {
62 VLOG(2) << "ARC intent helper instance is not ready.";
63 if (out_error_code)
64 *out_error_code = ActivityIconLoader::GetResult::FAILED_ARC_NOT_READY;
65 return nullptr;
66 }
67
68 auto* instance = ARC_GET_INSTANCE_FOR_METHOD(intent_helper_holder,
69 RequestActivityIcons);
70 if (!instance && out_error_code)
71 *out_error_code = ActivityIconLoader::GetResult::FAILED_ARC_NOT_SUPPORTED;
49 return instance; 72 return instance;
50 } 73 }
51 74
75 std::unique_ptr<ActivityIconLoader::ActivityToIconsMap> ResizeAndEncodeIcons(
76 std::vector<mojom::ActivityIconPtr> icons) {
77 auto result = base::MakeUnique<ActivityIconLoader::ActivityToIconsMap>();
78 for (size_t i = 0; i < icons.size(); ++i) {
79 static const size_t kBytesPerPixel = 4;
80 const mojom::ActivityIconPtr& icon = icons.at(i);
81 if (icon->width > kMaxIconSizeInPx || icon->height > kMaxIconSizeInPx ||
82 icon->width == 0 || icon->height == 0 ||
83 icon->icon.size() != (icon->width * icon->height * kBytesPerPixel)) {
84 continue;
85 }
86
87 SkBitmap bitmap;
88 bitmap.allocPixels(SkImageInfo::MakeN32Premul(icon->width, icon->height));
89 if (!bitmap.getPixels())
90 continue;
91 DCHECK_GE(bitmap.getSafeSize(), icon->icon.size());
92 memcpy(bitmap.getPixels(), &icon->icon.front(), icon->icon.size());
93
94 gfx::ImageSkia original(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
95
96 // Resize the original icon to the sizes intent_helper needs.
97 gfx::ImageSkia icon_large(gfx::ImageSkiaOperations::CreateResizedImage(
98 original, skia::ImageOperations::RESIZE_BEST,
99 gfx::Size(kLargeIconSizeInDip, kLargeIconSizeInDip)));
100 gfx::ImageSkia icon_small(gfx::ImageSkiaOperations::CreateResizedImage(
101 original, skia::ImageOperations::RESIZE_BEST,
102 gfx::Size(kSmallIconSizeInDip, kSmallIconSizeInDip)));
103 gfx::Image icon16(icon_small);
104 gfx::Image icon20(icon_large);
105
106 // Encode the icon as PNG data, and then as data: URL.
107 scoped_refptr<base::RefCountedMemory> img = icon16.As1xPNGBytes();
108 if (!img)
109 continue;
110 std::string encoded;
111 base::Base64Encode(base::StringPiece(img->front_as<char>(), img->size()),
112 &encoded);
113 scoped_refptr<base::RefCountedData<GURL>> dataurl(
114 new base::RefCountedData<GURL>(GURL(kPngDataUrlPrefix + encoded)));
115
116 const std::string activity_name = icon->activity->activity_name.has_value()
117 ? (*icon->activity->activity_name)
118 : std::string();
119 result->insert(
120 std::make_pair(ActivityIconLoader::ActivityName(
121 icon->activity->package_name, activity_name),
122 ActivityIconLoader::Icons(icon16, icon20, dataurl)));
123 }
124
125 return result;
126 }
127
52 } // namespace 128 } // namespace
53 129
54 ActivityIconLoader::Icons::Icons( 130 ActivityIconLoader::Icons::Icons(
55 const gfx::Image& icon16, 131 const gfx::Image& icon16,
56 const gfx::Image& icon20, 132 const gfx::Image& icon20,
57 const scoped_refptr<base::RefCountedData<GURL>>& icon16_dataurl) 133 const scoped_refptr<base::RefCountedData<GURL>>& icon16_dataurl)
58 : icon16(icon16), icon20(icon20), icon16_dataurl(icon16_dataurl) {} 134 : icon16(icon16), icon20(icon20), icon16_dataurl(icon16_dataurl) {}
59 135
60 ActivityIconLoader::Icons::Icons(const Icons& other) = default; 136 ActivityIconLoader::Icons::Icons(const Icons& other) = default;
61 137
62 ActivityIconLoader::Icons::~Icons() = default; 138 ActivityIconLoader::Icons::~Icons() = default;
63 139
64 ActivityIconLoader::ActivityName::ActivityName(const std::string& package_name, 140 ActivityIconLoader::ActivityName::ActivityName(const std::string& package_name,
65 const std::string& activity_name) 141 const std::string& activity_name)
66 : package_name(package_name), activity_name(activity_name) {} 142 : package_name(package_name), activity_name(activity_name) {}
67 143
68 bool ActivityIconLoader::ActivityName::operator<( 144 bool ActivityIconLoader::ActivityName::operator<(
69 const ActivityName& other) const { 145 const ActivityName& other) const {
70 return std::tie(package_name, activity_name) < 146 return std::tie(package_name, activity_name) <
71 std::tie(other.package_name, other.activity_name); 147 std::tie(other.package_name, other.activity_name);
72 } 148 }
73 149
74 ActivityIconLoader::ActivityIconLoader() 150 ActivityIconLoader::ActivityIconLoader()
75 : scale_factor_(GetSupportedScaleFactor()) {} 151 : scale_factor_(GetSupportedScaleFactor()), weak_ptr_factory_(this) {}
76 152
77 ActivityIconLoader::~ActivityIconLoader() {} 153 ActivityIconLoader::~ActivityIconLoader() = default;
78 154
79 void ActivityIconLoader::InvalidateIcons(const std::string& package_name) { 155 void ActivityIconLoader::InvalidateIcons(const std::string& package_name) {
80 DCHECK(thread_checker_.CalledOnValidThread()); 156 DCHECK(thread_checker_.CalledOnValidThread());
81 for (auto it = cached_icons_.begin(); it != cached_icons_.end();) { 157 for (auto it = cached_icons_.begin(); it != cached_icons_.end();) {
82 if (it->first.package_name == package_name) 158 if (it->first.package_name == package_name)
83 it = cached_icons_.erase(it); 159 it = cached_icons_.erase(it);
84 else 160 else
85 ++it; 161 ++it;
86 } 162 }
87 } 163 }
(...skipping 16 matching lines...) Expand all
104 result->insert(std::make_pair(activity, it->second)); 180 result->insert(std::make_pair(activity, it->second));
105 } 181 }
106 } 182 }
107 183
108 if (activities_to_fetch.empty()) { 184 if (activities_to_fetch.empty()) {
109 // If there's nothing to fetch, run the callback now. 185 // If there's nothing to fetch, run the callback now.
110 cb.Run(std::move(result)); 186 cb.Run(std::move(result));
111 return GetResult::SUCCEEDED_SYNC; 187 return GetResult::SUCCEEDED_SYNC;
112 } 188 }
113 189
114 ArcIntentHelperBridge::GetResult error_code; 190 GetResult error_code;
115 auto* instance = GetInstanceForRequestActivityIcons(&error_code); 191 auto* instance = GetInstanceForRequestActivityIcons(&error_code);
116 if (!instance) { 192 if (!instance) {
117 // The mojo channel is not yet ready (or not supported at all). Run the 193 // The mojo channel is not yet ready (or not supported at all). Run the
118 // callback with |result| that could be empty. 194 // callback with |result| that could be empty.
119 cb.Run(std::move(result)); 195 cb.Run(std::move(result));
120 switch (error_code) { 196 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 } 197 }
128 198
129 // Fetch icons from ARC. 199 // Fetch icons from ARC.
130 instance->RequestActivityIcons( 200 instance->RequestActivityIcons(
131 std::move(activities_to_fetch), mojom::ScaleFactor(scale_factor_), 201 std::move(activities_to_fetch), mojom::ScaleFactor(scale_factor_),
132 base::Bind(&ActivityIconLoader::OnIconsReady, this, base::Passed(&result), 202 base::Bind(&ActivityIconLoader::OnIconsReady,
133 cb)); 203 weak_ptr_factory_.GetWeakPtr(), base::Passed(&result), cb));
134 return GetResult::SUCCEEDED_ASYNC; 204 return GetResult::SUCCEEDED_ASYNC;
135 } 205 }
136 206
137 void ActivityIconLoader::OnIconsResizedForTesting( 207 void ActivityIconLoader::OnIconsResizedForTesting(
138 const OnIconsReadyCallback& cb, 208 const OnIconsReadyCallback& cb,
139 std::unique_ptr<ActivityToIconsMap> result) { 209 std::unique_ptr<ActivityToIconsMap> result) {
140 OnIconsResized(base::MakeUnique<ActivityToIconsMap>(), cb, std::move(result)); 210 OnIconsResized(base::MakeUnique<ActivityToIconsMap>(), cb, std::move(result));
141 } 211 }
142 212
143 void ActivityIconLoader::AddCacheEntryForTesting(const ActivityName& activity) { 213 void ActivityIconLoader::AddCacheEntryForTesting(const ActivityName& activity) {
(...skipping 15 matching lines...) Expand all
159 } 229 }
160 230
161 void ActivityIconLoader::OnIconsReady( 231 void ActivityIconLoader::OnIconsReady(
162 std::unique_ptr<ActivityToIconsMap> cached_result, 232 std::unique_ptr<ActivityToIconsMap> cached_result,
163 const OnIconsReadyCallback& cb, 233 const OnIconsReadyCallback& cb,
164 std::vector<mojom::ActivityIconPtr> icons) { 234 std::vector<mojom::ActivityIconPtr> icons) {
165 DCHECK(thread_checker_.CalledOnValidThread()); 235 DCHECK(thread_checker_.CalledOnValidThread());
166 ArcServiceManager* manager = ArcServiceManager::Get(); 236 ArcServiceManager* manager = ArcServiceManager::Get();
167 base::PostTaskAndReplyWithResult( 237 base::PostTaskAndReplyWithResult(
168 manager->blocking_task_runner().get(), FROM_HERE, 238 manager->blocking_task_runner().get(), FROM_HERE,
169 base::Bind(&ActivityIconLoader::ResizeAndEncodeIcons, 239 base::Bind(&ResizeAndEncodeIcons, base::Passed(&icons)),
170 base::Passed(&icons)), 240 base::Bind(&ActivityIconLoader::OnIconsResized,
171 base::Bind(&ActivityIconLoader::OnIconsResized, this, 241 weak_ptr_factory_.GetWeakPtr(), base::Passed(&cached_result),
172 base::Passed(&cached_result), cb)); 242 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 } 243 }
229 244
230 void ActivityIconLoader::OnIconsResized( 245 void ActivityIconLoader::OnIconsResized(
231 std::unique_ptr<ActivityToIconsMap> cached_result, 246 std::unique_ptr<ActivityToIconsMap> cached_result,
232 const OnIconsReadyCallback& cb, 247 const OnIconsReadyCallback& cb,
233 std::unique_ptr<ActivityToIconsMap> result) { 248 std::unique_ptr<ActivityToIconsMap> result) {
234 DCHECK(thread_checker_.CalledOnValidThread()); 249 DCHECK(thread_checker_.CalledOnValidThread());
235 // Update |cached_icons_|. 250 // Update |cached_icons_|.
236 for (const auto& kv : *result) { 251 for (const auto& kv : *result) {
237 cached_icons_.erase(kv.first); 252 cached_icons_.erase(kv.first);
238 cached_icons_.insert(std::make_pair(kv.first, kv.second)); 253 cached_icons_.insert(std::make_pair(kv.first, kv.second));
239 } 254 }
240 255
241 // Merge the results that were obtained from cache before doing IPC. 256 // Merge the results that were obtained from cache before doing IPC.
242 result->insert(cached_result->begin(), cached_result->end()); 257 result->insert(cached_result->begin(), cached_result->end());
243 cb.Run(std::move(result)); 258 cb.Run(std::move(result));
244 } 259 }
245 260
261 } // namespace internal
246 } // namespace arc 262 } // namespace arc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698