Commit f7278321 authored by Matt Menard's avatar Matt Menard Committed by Commit Bot

Create AppInfoGenerator to collect app inventory

Bug: 1058453
Change-Id: I7b3a610777ac70a7136045585036e4f714217cab
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2085874
Commit-Queue: Matt Menard <mattme@google.com>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarSergey Poromov <poromov@chromium.org>
Cr-Commit-Position: refs/heads/master@{#751447}
parent 0b229cea
......@@ -1960,6 +1960,8 @@ source_set("chromeos") {
"policy/single_app_install_event_log.h",
"policy/status_collector/activity_storage.cc",
"policy/status_collector/activity_storage.h",
"policy/status_collector/app_info_generator.cc",
"policy/status_collector/app_info_generator.h",
"policy/status_collector/child_activity_storage.cc",
"policy/status_collector/child_activity_storage.h",
"policy/status_collector/child_status_collector.cc",
......@@ -3023,6 +3025,7 @@ source_set("unit_tests") {
"policy/secondary_google_account_signin_policy_handler_unittest.cc",
"policy/server_backed_state_keys_broker_unittest.cc",
"policy/single_app_install_event_log_unittest.cc",
"policy/status_collector/app_info_generator_unittest.cc",
"policy/status_collector/interval_map_unittest.cc",
"policy/status_uploader_unittest.cc",
"policy/system_log_uploader_unittest.cc",
......
// Copyright 2020 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/policy/status_collector/app_info_generator.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_provider_factory.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/services/app_service/public/cpp/app_registry_cache.h"
#include "chrome/services/app_service/public/cpp/app_update.h"
#include "components/policy/proto/device_management_backend.pb.h"
namespace em = enterprise_management;
namespace {
em::AppInfo::Status ExtractStatus(const apps::mojom::Readiness readiness) {
switch (readiness) {
case apps::mojom::Readiness::kReady:
return em::AppInfo::Status::AppInfo_Status_STATUS_INSTALLED;
case apps::mojom::Readiness::kUninstalledByUser:
return em::AppInfo::Status::AppInfo_Status_STATUS_UNINSTALLED;
case apps::mojom::Readiness::kDisabledByBlacklist:
case apps::mojom::Readiness::kDisabledByPolicy:
case apps::mojom::Readiness::kDisabledByUser:
case apps::mojom::Readiness::kTerminated:
return em::AppInfo::Status::AppInfo_Status_STATUS_DISABLED;
case apps::mojom::Readiness::kUnknown:
return em::AppInfo::Status::AppInfo_Status_STATUS_UNKNOWN;
}
}
em::AppInfo::AppType ExtractAppType(const apps::mojom::AppType app_type) {
switch (app_type) {
case apps::mojom::AppType::kArc:
return em::AppInfo::AppType::AppInfo_AppType_TYPE_ARC;
case apps::mojom::AppType::kBuiltIn:
return em::AppInfo::AppType::AppInfo_AppType_TYPE_BUILTIN;
case apps::mojom::AppType::kCrostini:
return em::AppInfo::AppType::AppInfo_AppType_TYPE_CROSTINI;
case apps::mojom::AppType::kExtension:
return em::AppInfo::AppType::AppInfo_AppType_TYPE_EXTENSION;
case apps::mojom::AppType::kWeb:
return em::AppInfo::AppType::AppInfo_AppType_TYPE_WEB;
case apps::mojom::AppType::kMacNative:
case apps::mojom::AppType::kUnknown:
return em::AppInfo::AppType::AppInfo_AppType_TYPE_UNKNOWN;
}
}
} // namespace
namespace policy {
AppInfoGenerator::AppInfoGenerator(Profile* profile) : profile_(profile) {}
std::vector<em::AppInfo> AppInfoGenerator::Generate() const {
std::vector<em::AppInfo> app_infos;
apps::AppServiceProxy* app_service_proxy =
apps::AppServiceProxyFactory::GetForProfile(profile_);
web_app::WebAppProvider* web_app_provider =
web_app::WebAppProviderFactory::GetForProfile(profile_);
if (!app_service_proxy || !web_app_provider) {
LOG(WARNING) << "Could not get app providers. Returning empty app list.";
return app_infos;
}
app_service_proxy->AppRegistryCache().ForEachApp(
[&app_infos, web_app_provider](const apps::AppUpdate& update) {
em::AppInfo info;
auto is_web_app = update.AppType() == apps::mojom::AppType::kWeb;
if (!is_web_app) {
info.set_app_id(update.AppId());
info.set_app_name(update.Name());
} else {
auto launch_url = web_app_provider->registrar()
.GetAppLaunchURL(update.AppId())
.GetOrigin()
.spec();
info.set_app_id(launch_url);
info.set_app_name(launch_url);
}
info.set_status(ExtractStatus(update.Readiness()));
info.set_version(update.Version());
info.set_app_type(ExtractAppType(update.AppType()));
app_infos.push_back(info);
});
return app_infos;
}
} // namespace policy
// Copyright 2020 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.
#ifndef CHROME_BROWSER_CHROMEOS_POLICY_STATUS_COLLECTOR_APP_INFO_GENERATOR_H_
#define CHROME_BROWSER_CHROMEOS_POLICY_STATUS_COLLECTOR_APP_INFO_GENERATOR_H_
#include <memory>
#include <string>
#include <vector>
class Profile;
namespace enterprise_management {
class AppInfo;
} // namespace enterprise_management
namespace policy {
// A class that is responsible for collecting application inventory and usage
// information.
class AppInfoGenerator {
public:
explicit AppInfoGenerator(Profile* profile);
AppInfoGenerator(const AppInfoGenerator&) = delete;
AppInfoGenerator& operator=(const AppInfoGenerator&) = delete;
~AppInfoGenerator() = default;
std::vector<enterprise_management::AppInfo> Generate() const;
private:
Profile* const profile_;
};
} // namespace policy
#endif // CHROME_BROWSER_CHROMEOS_POLICY_STATUS_COLLECTOR_APP_INFO_GENERATOR_H_
// Copyright 2020 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/policy/status_collector/app_info_generator.h"
#include <memory>
#include "base/test/bind_test_util.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/web_applications/test/test_app_registrar.h"
#include "chrome/browser/web_applications/test/test_install_finalizer.h"
#include "chrome/browser/web_applications/test/test_web_app_provider.h"
#include "chrome/browser/web_applications/test/test_web_app_registry_controller.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_provider_factory.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/test/base/testing_profile.h"
#include "components/policy/proto/device_management_backend.pb.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::AllOf;
using ::testing::ElementsAre;
using ::testing::Property;
namespace em = enterprise_management;
namespace policy {
auto EqApp(const std::string& app_id,
const std::string& name,
const em::AppInfo::Status status,
const std::string& version,
const em::AppInfo::AppType app_type) {
return AllOf(Property(&em::AppInfo::app_id, app_id),
Property(&em::AppInfo::app_name, name),
Property(&em::AppInfo::status, status),
Property(&em::AppInfo::version, version),
Property(&em::AppInfo::app_type, app_type));
}
class AppInfoGeneratorTest : public ::testing::Test {
protected:
static apps::mojom::AppPtr MakeApp(const std::string& app_id,
const std::string& name,
const apps::mojom::Readiness readiness,
const std::string& version,
const apps::mojom::AppType app_type) {
auto app = apps::mojom::App::New();
app->app_id = app_id;
app->name = name;
app->readiness = readiness;
app->version = version;
app->app_type = app_type;
return app;
}
void SetUp() override {
profile_ = std::make_unique<TestingProfile>();
web_app::WebAppProviderFactory::GetInstance()->SetTestingFactoryAndUse(
profile_.get(),
base::BindLambdaForTesting([this](content::BrowserContext* context)
-> std::unique_ptr<KeyedService> {
Profile* profile = Profile::FromBrowserContext(context);
auto provider =
std::make_unique<web_app::TestWebAppProvider>(profile);
auto app_registrar = std::make_unique<web_app::TestAppRegistrar>();
app_registrar_ = app_registrar.get();
provider->SetRegistrar(std::move(app_registrar));
provider->Start();
return provider;
}));
}
apps::AppRegistryCache& GetCache() {
apps::AppServiceProxy* proxy =
apps::AppServiceProxyFactory::GetForProfile(profile_.get());
return proxy->AppRegistryCache();
}
std::unique_ptr<AppInfoGenerator> GetGenerator() {
return std::make_unique<AppInfoGenerator>(profile_.get());
}
web_app::TestAppRegistrar& web_app_registrar() { return *app_registrar_; }
Profile& profile() { return *profile_; }
private:
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<TestingProfile> profile_;
web_app::TestAppRegistrar* app_registrar_;
};
TEST_F(AppInfoGeneratorTest, GenerateInventoryList) {
std::vector<apps::mojom::AppPtr> deltas;
deltas.push_back(MakeApp("a", "FirstApp",
apps::mojom::Readiness::kDisabledByPolicy, "1.1",
apps::mojom::AppType::kArc));
deltas.push_back(MakeApp("b", "SecondApp", apps::mojom::Readiness::kReady,
"1.2", apps::mojom::AppType::kExtension));
deltas.push_back(MakeApp("c", "ThirdApp",
apps::mojom::Readiness::kUninstalledByUser, "",
apps::mojom::AppType::kCrostini));
GetCache().OnApps(std::move(deltas));
auto app_infos = GetGenerator()->Generate();
EXPECT_THAT(
app_infos,
ElementsAre(EqApp("a", "FirstApp", em::AppInfo_Status_STATUS_DISABLED,
"1.1", em::AppInfo_AppType_TYPE_ARC),
EqApp("b", "SecondApp", em::AppInfo_Status_STATUS_INSTALLED,
"1.2", em::AppInfo_AppType_TYPE_EXTENSION),
EqApp("c", "ThirdApp", em::AppInfo_Status_STATUS_UNINSTALLED,
"", em::AppInfo_AppType_TYPE_CROSTINI)));
}
TEST_F(AppInfoGeneratorTest, GenerateWebApp) {
std::vector<apps::mojom::AppPtr> deltas;
deltas.push_back(MakeApp("c", "App",
apps::mojom::Readiness::kUninstalledByUser, "",
apps::mojom::AppType::kWeb));
GetCache().OnApps(std::move(deltas));
web_app::TestAppRegistrar::AppInfo app = {
GURL::EmptyGURL(), web_app::ExternalInstallSource::kExternalDefault,
GURL("http://app.com/app")};
web_app_registrar().AddExternalApp("c", app);
auto app_infos = GetGenerator()->Generate();
EXPECT_THAT(app_infos,
ElementsAre(EqApp("http://app.com/", "http://app.com/",
em::AppInfo_Status_STATUS_UNINSTALLED, "",
em::AppInfo_AppType_TYPE_WEB)));
}
} // namespace policy
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment