blob: ee4219a3bf98fedb814994641dd73984529edaab [file] [log] [blame]
// Copyright (c) 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/file_manager/crostini_file_tasks.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/base64.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/chromeos/crostini/crostini_registry_service.h"
#include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h"
#include "chrome/browser/chromeos/crostini/crostini_util.h"
#include "chrome/browser/chromeos/file_manager/app_id.h"
#include "chrome/browser/chromeos/file_manager/path_util.h"
#include "extensions/browser/entry_info.h"
#include "storage/browser/fileapi/file_system_url.h"
#include "ui/base/layout.h"
#include "ui/display/types/display_constants.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "url/gurl.h"
namespace file_manager {
namespace file_tasks {
namespace {
constexpr base::TimeDelta kIconLoadTimeout =
base::TimeDelta::FromMilliseconds(100);
constexpr size_t kIconSizeInDip = 16;
GURL GeneratePNGDataUrl(const SkBitmap& sk_bitmap) {
std::vector<unsigned char> output;
gfx::PNGCodec::EncodeBGRASkBitmap(sk_bitmap, false /* discard_transparency */,
&output);
std::string encoded;
base::Base64Encode(
base::StringPiece(reinterpret_cast<const char*>(output.data()),
output.size()),
&encoded);
return GURL("data:image/png;base64," + encoded);
}
void OnAppIconsLoaded(Profile* profile,
const std::vector<std::string>& app_ids,
ui::ScaleFactor scale_factor,
std::vector<FullTaskDescriptor>* result_list,
base::OnceClosure completion_closure,
const std::vector<gfx::ImageSkia>& icons) {
DCHECK(!app_ids.empty());
DCHECK_EQ(app_ids.size(), icons.size());
float scale = ui::GetScaleForScaleFactor(scale_factor);
crostini::CrostiniRegistryService* registry_service =
crostini::CrostiniRegistryServiceFactory::GetForProfile(profile);
for (size_t i = 0; i < app_ids.size(); ++i) {
result_list->push_back(FullTaskDescriptor(
TaskDescriptor(app_ids[i], TASK_TYPE_CROSTINI_APP,
kCrostiniAppActionID),
registry_service->GetRegistration(app_ids[i])->Name(),
extensions::api::file_manager_private::Verb::VERB_OPEN_WITH,
GeneratePNGDataUrl(icons[i].GetRepresentation(scale).sk_bitmap()),
false /* is_default */, false /* is_generic */));
}
std::move(completion_closure).Run();
}
} // namespace
void FindCrostiniTasks(Profile* profile,
const std::vector<extensions::EntryInfo>& entries,
std::vector<FullTaskDescriptor>* result_list,
base::OnceClosure completion_closure) {
if (!IsCrostiniUIAllowedForProfile(profile)) {
std::move(completion_closure).Run();
return;
}
std::set<std::string> target_mime_types;
for (const extensions::EntryInfo& entry : entries)
target_mime_types.insert(entry.mime_type);
std::vector<std::string> result_app_ids;
crostini::CrostiniRegistryService* registry_service =
crostini::CrostiniRegistryServiceFactory::GetForProfile(profile);
for (const std::string& app_id : registry_service->GetRegisteredAppIds()) {
crostini::CrostiniRegistryService::Registration registration =
*registry_service->GetRegistration(app_id);
const std::set<std::string>& supported_mime_types =
registration.MimeTypes();
bool had_unsupported_mime_type = false;
for (const std::string& target_mime_type : target_mime_types) {
if (supported_mime_types.find(target_mime_type) !=
supported_mime_types.end())
continue;
had_unsupported_mime_type = true;
break;
}
if (had_unsupported_mime_type)
continue;
result_app_ids.push_back(app_id);
}
if (result_app_ids.empty()) {
std::move(completion_closure).Run();
return;
}
ui::ScaleFactor scale_factor = ui::GetSupportedScaleFactors().back();
LoadIcons(
profile, result_app_ids, kIconSizeInDip, scale_factor, kIconLoadTimeout,
base::BindOnce(OnAppIconsLoaded, profile, result_app_ids, scale_factor,
result_list, std::move(completion_closure)));
}
void ExecuteCrostiniTask(
Profile* profile,
const TaskDescriptor& task,
const std::vector<storage::FileSystemURL>& file_system_urls,
const FileTaskFinishedCallback& done) {
DCHECK(IsCrostiniUIAllowedForProfile(profile));
std::vector<std::string> files;
for (const storage::FileSystemURL& file_system_url : file_system_urls) {
files.emplace_back(util::ConvertFileSystemURLToPathInsideCrostini(
profile, file_system_url));
}
LaunchCrostiniApp(profile, task.app_id, display::kInvalidDisplayId, files);
}
} // namespace file_tasks
} // namespace file_manager