| Index: components/arc/intent_helper/activity_icon_loader.cc
|
| diff --git a/components/arc/intent_helper/activity_icon_loader.cc b/components/arc/intent_helper/activity_icon_loader.cc
|
| index 715b6bd8db8fb25b16490d613c3390e06b122770..042487231cd330de62ea8daf3668ef1af9a39dc6 100644
|
| --- a/components/arc/intent_helper/activity_icon_loader.cc
|
| +++ b/components/arc/intent_helper/activity_icon_loader.cc
|
| @@ -12,14 +12,17 @@
|
| #include "base/base64.h"
|
| #include "base/bind.h"
|
| #include "base/memory/ptr_util.h"
|
| +#include "base/memory/ref_counted.h"
|
| #include "base/task_runner_util.h"
|
| #include "components/arc/arc_bridge_service.h"
|
| #include "components/arc/arc_service_manager.h"
|
| +#include "components/arc/arc_util.h"
|
| #include "ui/base/layout.h"
|
| #include "ui/gfx/image/image_skia.h"
|
| #include "ui/gfx/image/image_skia_operations.h"
|
|
|
| namespace arc {
|
| +namespace internal {
|
|
|
| namespace {
|
|
|
| @@ -36,19 +39,99 @@ ui::ScaleFactor GetSupportedScaleFactor() {
|
|
|
| // Returns an instance for calling RequestActivityIcons().
|
| mojom::IntentHelperInstance* GetInstanceForRequestActivityIcons(
|
| - ArcIntentHelperBridge::GetResult* out_error_code) {
|
| - if (!ArcIntentHelperBridge::IsIntentHelperAvailable(out_error_code))
|
| + ActivityIconLoader::GetResult* out_error_code) {
|
| + auto* arc_service_manager = ArcServiceManager::Get();
|
| + if (!arc_service_manager) {
|
| + // TODO(hidehiko): IsArcAvailable() looks not the condition to be checked
|
| + // here, because ArcServiceManager instance is created regardless of ARC
|
| + // availability. This happens only before MessageLoop starts or after
|
| + // MessageLoop stops, practically.
|
| + // Also, returning FAILED_ARC_NOT_READY looks problematic at the moment,
|
| + // because ArcProcessTask::StartIconLoading accesses to
|
| + // ArcServiceManager::Get() return value, which can be nullptr.
|
| + if (!IsArcAvailable()) {
|
| + VLOG(2) << "ARC bridge is not supported.";
|
| + if (out_error_code) {
|
| + *out_error_code =
|
| + ActivityIconLoader::GetResult::FAILED_ARC_NOT_SUPPORTED;
|
| + }
|
| + } else {
|
| + VLOG(2) << "ARC bridge is not ready.";
|
| + if (out_error_code)
|
| + *out_error_code = ActivityIconLoader::GetResult::FAILED_ARC_NOT_READY;
|
| + }
|
| return nullptr;
|
| - auto* instance = ARC_GET_INSTANCE_FOR_METHOD(
|
| - ArcServiceManager::Get()->arc_bridge_service()->intent_helper(),
|
| - RequestActivityIcons);
|
| - if (!instance && out_error_code) {
|
| - *out_error_code =
|
| - ArcIntentHelperBridge::GetResult::FAILED_ARC_NOT_SUPPORTED;
|
| }
|
| +
|
| + auto* intent_helper_holder =
|
| + arc_service_manager->arc_bridge_service()->intent_helper();
|
| + if (!intent_helper_holder->has_instance()) {
|
| + VLOG(2) << "ARC intent helper instance is not ready.";
|
| + if (out_error_code)
|
| + *out_error_code = ActivityIconLoader::GetResult::FAILED_ARC_NOT_READY;
|
| + return nullptr;
|
| + }
|
| +
|
| + auto* instance = ARC_GET_INSTANCE_FOR_METHOD(intent_helper_holder,
|
| + RequestActivityIcons);
|
| + if (!instance && out_error_code)
|
| + *out_error_code = ActivityIconLoader::GetResult::FAILED_ARC_NOT_SUPPORTED;
|
| return instance;
|
| }
|
|
|
| +std::unique_ptr<ActivityIconLoader::ActivityToIconsMap> ResizeAndEncodeIcons(
|
| + std::vector<mojom::ActivityIconPtr> icons) {
|
| + auto result = base::MakeUnique<ActivityIconLoader::ActivityToIconsMap>();
|
| + for (size_t i = 0; i < icons.size(); ++i) {
|
| + static const size_t kBytesPerPixel = 4;
|
| + const mojom::ActivityIconPtr& icon = icons.at(i);
|
| + if (icon->width > kMaxIconSizeInPx || icon->height > kMaxIconSizeInPx ||
|
| + icon->width == 0 || icon->height == 0 ||
|
| + icon->icon.size() != (icon->width * icon->height * kBytesPerPixel)) {
|
| + continue;
|
| + }
|
| +
|
| + SkBitmap bitmap;
|
| + bitmap.allocPixels(SkImageInfo::MakeN32Premul(icon->width, icon->height));
|
| + if (!bitmap.getPixels())
|
| + continue;
|
| + DCHECK_GE(bitmap.getSafeSize(), icon->icon.size());
|
| + memcpy(bitmap.getPixels(), &icon->icon.front(), icon->icon.size());
|
| +
|
| + gfx::ImageSkia original(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
|
| +
|
| + // Resize the original icon to the sizes intent_helper needs.
|
| + gfx::ImageSkia icon_large(gfx::ImageSkiaOperations::CreateResizedImage(
|
| + original, skia::ImageOperations::RESIZE_BEST,
|
| + gfx::Size(kLargeIconSizeInDip, kLargeIconSizeInDip)));
|
| + gfx::ImageSkia icon_small(gfx::ImageSkiaOperations::CreateResizedImage(
|
| + original, skia::ImageOperations::RESIZE_BEST,
|
| + gfx::Size(kSmallIconSizeInDip, kSmallIconSizeInDip)));
|
| + gfx::Image icon16(icon_small);
|
| + gfx::Image icon20(icon_large);
|
| +
|
| + // Encode the icon as PNG data, and then as data: URL.
|
| + scoped_refptr<base::RefCountedMemory> img = icon16.As1xPNGBytes();
|
| + if (!img)
|
| + continue;
|
| + std::string encoded;
|
| + base::Base64Encode(base::StringPiece(img->front_as<char>(), img->size()),
|
| + &encoded);
|
| + scoped_refptr<base::RefCountedData<GURL>> dataurl(
|
| + new base::RefCountedData<GURL>(GURL(kPngDataUrlPrefix + encoded)));
|
| +
|
| + const std::string activity_name = icon->activity->activity_name.has_value()
|
| + ? (*icon->activity->activity_name)
|
| + : std::string();
|
| + result->insert(
|
| + std::make_pair(ActivityIconLoader::ActivityName(
|
| + icon->activity->package_name, activity_name),
|
| + ActivityIconLoader::Icons(icon16, icon20, dataurl)));
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| } // namespace
|
|
|
| ActivityIconLoader::Icons::Icons(
|
| @@ -72,9 +155,9 @@ bool ActivityIconLoader::ActivityName::operator<(
|
| }
|
|
|
| ActivityIconLoader::ActivityIconLoader()
|
| - : scale_factor_(GetSupportedScaleFactor()) {}
|
| + : scale_factor_(GetSupportedScaleFactor()), weak_ptr_factory_(this) {}
|
|
|
| -ActivityIconLoader::~ActivityIconLoader() {}
|
| +ActivityIconLoader::~ActivityIconLoader() = default;
|
|
|
| void ActivityIconLoader::InvalidateIcons(const std::string& package_name) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| @@ -111,26 +194,20 @@ ActivityIconLoader::GetResult ActivityIconLoader::GetActivityIcons(
|
| return GetResult::SUCCEEDED_SYNC;
|
| }
|
|
|
| - ArcIntentHelperBridge::GetResult error_code;
|
| + GetResult error_code;
|
| auto* instance = GetInstanceForRequestActivityIcons(&error_code);
|
| if (!instance) {
|
| // The mojo channel is not yet ready (or not supported at all). Run the
|
| // callback with |result| that could be empty.
|
| cb.Run(std::move(result));
|
| - switch (error_code) {
|
| - case ArcIntentHelperBridge::GetResult::FAILED_ARC_NOT_READY:
|
| - return GetResult(GetResult::FAILED_ARC_NOT_READY);
|
| - case ArcIntentHelperBridge::GetResult::FAILED_ARC_NOT_SUPPORTED:
|
| - return GetResult(GetResult::FAILED_ARC_NOT_SUPPORTED);
|
| - }
|
| - NOTREACHED();
|
| + return error_code;
|
| }
|
|
|
| // Fetch icons from ARC.
|
| instance->RequestActivityIcons(
|
| std::move(activities_to_fetch), mojom::ScaleFactor(scale_factor_),
|
| - base::Bind(&ActivityIconLoader::OnIconsReady, this, base::Passed(&result),
|
| - cb));
|
| + base::Bind(&ActivityIconLoader::OnIconsReady,
|
| + weak_ptr_factory_.GetWeakPtr(), base::Passed(&result), cb));
|
| return GetResult::SUCCEEDED_ASYNC;
|
| }
|
|
|
| @@ -166,65 +243,10 @@ void ActivityIconLoader::OnIconsReady(
|
| ArcServiceManager* manager = ArcServiceManager::Get();
|
| base::PostTaskAndReplyWithResult(
|
| manager->blocking_task_runner().get(), FROM_HERE,
|
| - base::Bind(&ActivityIconLoader::ResizeAndEncodeIcons,
|
| - base::Passed(&icons)),
|
| - base::Bind(&ActivityIconLoader::OnIconsResized, this,
|
| - base::Passed(&cached_result), cb));
|
| -}
|
| -
|
| -// static
|
| -std::unique_ptr<ActivityIconLoader::ActivityToIconsMap>
|
| -ActivityIconLoader::ResizeAndEncodeIcons(
|
| - std::vector<mojom::ActivityIconPtr> icons) {
|
| - std::unique_ptr<ActivityToIconsMap> result(new ActivityToIconsMap);
|
| -
|
| - for (size_t i = 0; i < icons.size(); ++i) {
|
| - static const size_t kBytesPerPixel = 4;
|
| - const mojom::ActivityIconPtr& icon = icons.at(i);
|
| - if (icon->width > kMaxIconSizeInPx || icon->height > kMaxIconSizeInPx ||
|
| - icon->width == 0 || icon->height == 0 ||
|
| - icon->icon.size() != (icon->width * icon->height * kBytesPerPixel)) {
|
| - continue;
|
| - }
|
| -
|
| - SkBitmap bitmap;
|
| - bitmap.allocPixels(SkImageInfo::MakeN32Premul(icon->width, icon->height));
|
| - if (!bitmap.getPixels())
|
| - continue;
|
| - DCHECK_GE(bitmap.getSafeSize(), icon->icon.size());
|
| - memcpy(bitmap.getPixels(), &icon->icon.front(), icon->icon.size());
|
| -
|
| - gfx::ImageSkia original(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
|
| -
|
| - // Resize the original icon to the sizes intent_helper needs.
|
| - gfx::ImageSkia icon_large(gfx::ImageSkiaOperations::CreateResizedImage(
|
| - original, skia::ImageOperations::RESIZE_BEST,
|
| - gfx::Size(kLargeIconSizeInDip, kLargeIconSizeInDip)));
|
| - gfx::ImageSkia icon_small(gfx::ImageSkiaOperations::CreateResizedImage(
|
| - original, skia::ImageOperations::RESIZE_BEST,
|
| - gfx::Size(kSmallIconSizeInDip, kSmallIconSizeInDip)));
|
| - gfx::Image icon16(icon_small);
|
| - gfx::Image icon20(icon_large);
|
| -
|
| - // Encode the icon as PNG data, and then as data: URL.
|
| - scoped_refptr<base::RefCountedMemory> img = icon16.As1xPNGBytes();
|
| - if (!img)
|
| - continue;
|
| - std::string encoded;
|
| - base::Base64Encode(base::StringPiece(img->front_as<char>(), img->size()),
|
| - &encoded);
|
| - scoped_refptr<base::RefCountedData<GURL>> dataurl(
|
| - new base::RefCountedData<GURL>(GURL(kPngDataUrlPrefix + encoded)));
|
| -
|
| - const std::string activity_name = icon->activity->activity_name.has_value()
|
| - ? (*icon->activity->activity_name)
|
| - : std::string();
|
| - result->insert(std::make_pair(
|
| - ActivityName(icon->activity->package_name, activity_name),
|
| - Icons(icon16, icon20, dataurl)));
|
| - }
|
| -
|
| - return result;
|
| + base::Bind(&ResizeAndEncodeIcons, base::Passed(&icons)),
|
| + base::Bind(&ActivityIconLoader::OnIconsResized,
|
| + weak_ptr_factory_.GetWeakPtr(), base::Passed(&cached_result),
|
| + cb));
|
| }
|
|
|
| void ActivityIconLoader::OnIconsResized(
|
| @@ -243,4 +265,5 @@ void ActivityIconLoader::OnIconsResized(
|
| cb.Run(std::move(result));
|
| }
|
|
|
| +} // namespace internal
|
| } // namespace arc
|
|
|