Commit a2597745 authored by nancy's avatar nancy Committed by Commit Bot

Update UI Shelf to use AppService to verify app_id.

For Crostini, Extension, built-in apps, the AppService is used to
valid the app id. For ARC apps, ArcAppListPrefs is used, as ARC apps
have some very special cases, e.g. PlayStore. ARC tests also assume
synchronous behaviour, and will need more refactoring so the AppService
can be used.

Related unit tests has been fixed. Extension apps in test cases use
OnExtensionLoaded to add extension apps, so set the extension name
so that we can use AppService to dump the apps name.

BUG=1002351

Change-Id: Ia7f589de82ca226eb05dd1706ab95229699d6fdb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1803015
Commit-Queue: Nancy Wang <nancylingwang@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#697525}
parent ee1e58c1
...@@ -445,6 +445,7 @@ void ExtensionApps::OnExtensionLoaded(content::BrowserContext* browser_context, ...@@ -445,6 +445,7 @@ void ExtensionApps::OnExtensionLoaded(content::BrowserContext* browser_context,
app->app_type = app_type_; app->app_type = app_type_;
app->app_id = extension->id(); app->app_id = extension->id();
app->readiness = apps::mojom::Readiness::kReady; app->readiness = apps::mojom::Readiness::kReady;
app->name = extension->name();
Publish(std::move(app)); Publish(std::move(app));
} }
......
...@@ -312,11 +312,10 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest { ...@@ -312,11 +312,10 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest {
manifest.SetInteger(extensions::manifest_keys::kManifestVersion, 2); manifest.SetInteger(extensions::manifest_keys::kManifestVersion, 2);
manifest.SetString(extensions::manifest_keys::kDescription, manifest.SetString(extensions::manifest_keys::kDescription,
"for testing pinned apps"); "for testing pinned apps");
// AppService checks the app's type. So set the
// AppService checks the app's type, so sets the type in manifest for // manifest_keys::kLaunchWebURL, so that the extension can get the type
// extensions. // from manifest value, and then AppService can get the extension's type.
if (base::FeatureList::IsEnabled(features::kAppServiceShelf)) manifest.SetString(extensions::manifest_keys::kLaunchWebURL, kWebAppUrl);
manifest.SetString(extensions::manifest_keys::kLaunchWebURL, kWebAppUrl);
base::DictionaryValue manifest_platform_app; base::DictionaryValue manifest_platform_app;
manifest_platform_app.SetString(extensions::manifest_keys::kName, manifest_platform_app.SetString(extensions::manifest_keys::kName,
...@@ -431,6 +430,11 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest { ...@@ -431,6 +430,11 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest {
manifest_web_app.SetInteger(extensions::manifest_keys::kManifestVersion, 2); manifest_web_app.SetInteger(extensions::manifest_keys::kManifestVersion, 2);
manifest_web_app.SetString(extensions::manifest_keys::kDescription, manifest_web_app.SetString(extensions::manifest_keys::kDescription,
"For testing"); "For testing");
// AppService checks the app's type. So set the
// manifest_keys::kLaunchWebURL, so that the extension can get the type
// from manifest value, and then AppService can get the extension's type.
manifest_web_app.SetString(extensions::manifest_keys::kLaunchWebURL,
kWebAppUrl);
web_app_ = Extension::Create(base::FilePath(), Manifest::UNPACKED, web_app_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
manifest_web_app, Extension::FROM_BOOKMARK, manifest_web_app, Extension::FROM_BOOKMARK,
kWebAppId, &error); kWebAppId, &error);
...@@ -526,6 +530,7 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest { ...@@ -526,6 +530,7 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest {
// Create and initialize the controller, owned by the test shell delegate. // Create and initialize the controller, owned by the test shell delegate.
void InitLauncherController() { void InitLauncherController() {
CreateLauncherController()->Init(); CreateLauncherController()->Init();
FlushMojoCallsForAppService();
} }
// Create and initialize the controller; create a tab and show the browser. // Create and initialize the controller; create a tab and show the browser.
...@@ -693,6 +698,7 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest { ...@@ -693,6 +698,7 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest {
app_list_syncable_service_->ProcessSyncChanges(FROM_HERE, app_list_syncable_service_->ProcessSyncChanges(FROM_HERE,
combined_sync_list); combined_sync_list);
} }
FlushMojoCallsForAppService();
} }
// Set the index at which the chrome icon should be. // Set the index at which the chrome icon should be.
...@@ -765,15 +771,7 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest { ...@@ -765,15 +771,7 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest {
} else if (app == extensionYoutubeApp_->id()) { } else if (app == extensionYoutubeApp_->id()) {
result += "youtube"; result += "youtube";
} else { } else {
const auto* extension = extension_registry_->GetExtensionById( result += GetAppNameFromAppService(app);
app, extensions::ExtensionRegistry::COMPATIBILITY);
if (extension && !extension->name().empty()) {
std::string name = extension->name();
name[0] = std::tolower(name[0]);
result += name;
} else {
result += "unknown";
}
} }
break; break;
} }
...@@ -818,15 +816,7 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest { ...@@ -818,15 +816,7 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest {
} }
} }
if (!arc_app_found) { if (!arc_app_found) {
const auto* extension = extension_registry_->GetExtensionById( result += GetAppNameFromAppService(app);
app, extensions::ExtensionRegistry::COMPATIBILITY);
if (extension && !extension->name().empty()) {
std::string name = extension->name();
name[0] = std::toupper(name[0]);
result += name;
} else {
result += "Unknown";
}
} }
} }
break; break;
...@@ -959,6 +949,12 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest { ...@@ -959,6 +949,12 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest {
// Allow AppService async callbacks to run. // Allow AppService async callbacks to run.
void WaitForAppService() { base::RunLoop().RunUntilIdle(); } void WaitForAppService() { base::RunLoop().RunUntilIdle(); }
// Flush mojo calls to allow AppService async callbacks to run.
void FlushMojoCallsForAppService() {
if (app_service_proxy_)
app_service_proxy_->FlushMojoCallsForTesting();
}
// Add extension and allow AppService async callbacks to run. // Add extension and allow AppService async callbacks to run.
void AddExtension(const Extension* extension) { void AddExtension(const Extension* extension) {
extension_service_->AddExtension(extension); extension_service_->AddExtension(extension);
...@@ -972,6 +968,16 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest { ...@@ -972,6 +968,16 @@ class ChromeLauncherControllerTest : public BrowserWithTestWindowTest {
WaitForAppService(); WaitForAppService();
} }
const std::string GetAppNameFromAppService(const std::string& app_id) {
std::string name = "Unknown";
if (!app_service_proxy_)
return name;
app_service_proxy_->AppRegistryCache().ForOneApp(
app_id,
[&name](const apps::AppUpdate& update) { name = update.Name(); });
return name;
}
// Needed for extension service & friends to work. // Needed for extension service & friends to work.
scoped_refptr<Extension> extension_chrome_; scoped_refptr<Extension> extension_chrome_;
scoped_refptr<Extension> extension1_; scoped_refptr<Extension> extension1_;
...@@ -1064,13 +1070,16 @@ class ChromeLauncherControllerExtendedShelfTest ...@@ -1064,13 +1070,16 @@ class ChromeLauncherControllerExtendedShelfTest
manifest.SetInteger(extensions::manifest_keys::kManifestVersion, 2); manifest.SetInteger(extensions::manifest_keys::kManifestVersion, 2);
manifest.SetString(extensions::manifest_keys::kDescription, manifest.SetString(extensions::manifest_keys::kDescription,
"for testing pinned apps"); "for testing pinned apps");
// AppService checks the app's type. So set the
// manifest_keys::kLaunchWebURL, so that the extension can get the type
// from manifest value, and then AppService can get the extension's type.
manifest.SetString(extensions::manifest_keys::kLaunchWebURL, kWebAppUrl);
const std::vector<std::pair<std::string, std::string>> extra_extensions = { const std::vector<std::pair<std::string, std::string>> extra_extensions = {
{extension_misc::kCalendarAppId, "Calendar"}, {extension_misc::kCalendarAppId, "Calendar"},
{extension_misc::kGoogleSheetsAppId, "Sheets"}, {extension_misc::kGoogleSheetsAppId, "Sheets"},
{extension_misc::kGoogleSlidesAppId, "Slides"}, {extension_misc::kGoogleSlidesAppId, "Slides"},
{extension_misc::kFilesManagerAppId, "Files"}, {extension_misc::kFilesManagerAppId, "Files"},
{app_list::kInternalAppIdCamera, "Camera"},
{extension_misc::kGooglePhotosAppId, "Photos"}, {extension_misc::kGooglePhotosAppId, "Photos"},
}; };
...@@ -3728,7 +3737,7 @@ TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest, ...@@ -3728,7 +3737,7 @@ TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
multi_user_util::GetAccountIdFromProfile(profile2)); multi_user_util::GetAccountIdFromProfile(profile2));
const std::string app_id = extension1_->id(); const std::string app_id = extension1_->id();
extension_service_->AddExtension(extension1_.get()); AddExtension(extension1_.get());
EXPECT_EQ(1, model_->item_count()); EXPECT_EQ(1, model_->item_count());
EXPECT_FALSE( EXPECT_FALSE(
...@@ -3751,6 +3760,7 @@ TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest, ...@@ -3751,6 +3760,7 @@ TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
// Switch to a new profile // Switch to a new profile
SwitchActiveUser(account_id2); SwitchActiveUser(account_id2);
FlushMojoCallsForAppService();
EXPECT_FALSE(launcher_controller_->IsAppPinned(app_id)); EXPECT_FALSE(launcher_controller_->IsAppPinned(app_id));
EXPECT_EQ(1, model_->item_count()); EXPECT_EQ(1, model_->item_count());
EXPECT_FALSE( EXPECT_FALSE(
...@@ -3758,6 +3768,7 @@ TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest, ...@@ -3758,6 +3768,7 @@ TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
// Switch back // Switch back
SwitchActiveUser(account_id); SwitchActiveUser(account_id);
FlushMojoCallsForAppService();
EXPECT_TRUE(launcher_controller_->IsAppPinned(app_id)); EXPECT_TRUE(launcher_controller_->IsAppPinned(app_id));
EXPECT_EQ(2, model_->item_count()); EXPECT_EQ(2, model_->item_count());
EXPECT_TRUE( EXPECT_TRUE(
...@@ -4284,6 +4295,8 @@ class ChromeLauncherControllerPlayStoreAvailabilityTest ...@@ -4284,6 +4295,8 @@ class ChromeLauncherControllerPlayStoreAvailabilityTest
void SetUp() override { void SetUp() override {
if (GetParam()) if (GetParam())
arc::SetArcAlwaysStartWithoutPlayStoreForTesting(); arc::SetArcAlwaysStartWithoutPlayStoreForTesting();
// To prevent crash on test exit and pending decode request.
ArcAppIcon::DisableSafeDecodingForTesting();
ArcDefaultAppList::UseTestAppsDirectory(); ArcDefaultAppList::UseTestAppsDirectory();
ChromeLauncherControllerTest::SetUp(); ChromeLauncherControllerTest::SetUp();
} }
...@@ -4633,6 +4646,8 @@ TEST_F(ChromeLauncherControllerDemoModeTest, PinnedAppsOnline) { ...@@ -4633,6 +4646,8 @@ TEST_F(ChromeLauncherControllerDemoModeTest, PinnedAppsOnline) {
profile()->GetTestingPrefService()->SetManagedPref( profile()->GetTestingPrefService()->SetManagedPref(
prefs::kPolicyPinnedLauncherApps, policy_value.CreateDeepCopy()); prefs::kPolicyPinnedLauncherApps, policy_value.CreateDeepCopy());
FlushMojoCallsForAppService();
// Since the device is online, all policy pinned apps are pinned. // Since the device is online, all policy pinned apps are pinned.
EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id())); EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
EXPECT_EQ(AppListControllerDelegate::PIN_FIXED, EXPECT_EQ(AppListControllerDelegate::PIN_FIXED,
...@@ -4682,6 +4697,7 @@ TEST_F(ChromeLauncherControllerDemoModeTest, PinnedAppsOffline) { ...@@ -4682,6 +4697,7 @@ TEST_F(ChromeLauncherControllerDemoModeTest, PinnedAppsOffline) {
profile()->GetTestingPrefService()->SetManagedPref( profile()->GetTestingPrefService()->SetManagedPref(
prefs::kPolicyPinnedLauncherApps, policy_value.CreateDeepCopy()); prefs::kPolicyPinnedLauncherApps, policy_value.CreateDeepCopy());
FlushMojoCallsForAppService();
// Since the device is online, the policy pinned apps that shouldn't be pinned // Since the device is online, the policy pinned apps that shouldn't be pinned
// in Demo Mode are unpinned. // in Demo Mode are unpinned.
...@@ -4727,6 +4743,7 @@ TEST_F(ChromeLauncherControllerTest, CrostiniTerminalPinUnpin) { ...@@ -4727,6 +4743,7 @@ TEST_F(ChromeLauncherControllerTest, CrostiniTerminalPinUnpin) {
// Reload after allowing Crostini UI // Reload after allowing Crostini UI
crostini::CrostiniTestHelper test_helper(profile()); crostini::CrostiniTestHelper test_helper(profile());
test_helper.ReInitializeAppServiceIntegration();
// TODO(crubug.com/918739): Fix pins are not refreshed on enabling Crostini. // TODO(crubug.com/918739): Fix pins are not refreshed on enabling Crostini.
// As a workaround add any app that triggers pin update. // As a workaround add any app that triggers pin update.
AddExtension(extension1_.get()); AddExtension(extension1_.get());
......
...@@ -170,34 +170,28 @@ std::string LauncherControllerHelper::GetAppID(content::WebContents* tab) { ...@@ -170,34 +170,28 @@ std::string LauncherControllerHelper::GetAppID(content::WebContents* tab) {
} }
bool LauncherControllerHelper::IsValidIDForCurrentUser( bool LauncherControllerHelper::IsValidIDForCurrentUser(
const std::string& id) const { const std::string& app_id) const {
const ArcAppListPrefs* arc_prefs = GetArcAppListPrefs(); if (IsValidIDForArcApp(app_id)) {
if (arc_prefs && arc_prefs->IsRegistered(id))
return true; return true;
}
if (base::FeatureList::IsEnabled(features::kAppServiceShelf)) {
return IsValidIDFromAppService(app_id);
}
crostini::CrostiniRegistryService* registry_service = crostini::CrostiniRegistryService* registry_service =
crostini::CrostiniRegistryServiceFactory::GetForProfile(profile_); crostini::CrostiniRegistryServiceFactory::GetForProfile(profile_);
if (registry_service && registry_service->IsCrostiniShelfAppId(id)) { if (registry_service && registry_service->IsCrostiniShelfAppId(app_id)) {
return crostini::IsCrostiniUIAllowedForProfile(profile_) && return crostini::IsCrostiniUIAllowedForProfile(profile_) &&
registry_service->GetRegistration(id).has_value(); registry_service->GetRegistration(app_id).has_value();
} }
if (app_list::IsInternalApp(id)) if (app_list::IsInternalApp(app_id)) {
return true; return true;
}
if (!GetExtensionByID(profile_, id)) if (!GetExtensionByID(profile_, app_id)) {
return false; return false;
if (id == arc::kPlayStoreAppId) {
if (!arc::IsArcAllowedForProfile(profile()) || !arc::IsPlayStoreAvailable())
return false;
const arc::ArcSessionManager* arc_session_manager =
arc::ArcSessionManager::Get();
DCHECK(arc_session_manager);
if (!arc_session_manager->IsAllowed())
return false;
if (!arc::IsArcPlayStoreEnabledForProfile(profile()) &&
arc::IsArcPlayStoreEnabledPreferenceManagedForProfile(profile()))
return false;
} }
return true; return true;
...@@ -295,3 +289,47 @@ void LauncherControllerHelper::ExtensionEnableFlowFinished() { ...@@ -295,3 +289,47 @@ void LauncherControllerHelper::ExtensionEnableFlowFinished() {
void LauncherControllerHelper::ExtensionEnableFlowAborted(bool user_initiated) { void LauncherControllerHelper::ExtensionEnableFlowAborted(bool user_initiated) {
extension_enable_flow_.reset(); extension_enable_flow_.reset();
} }
bool LauncherControllerHelper::IsValidIDForArcApp(
const std::string& app_id) const {
const ArcAppListPrefs* arc_prefs = GetArcAppListPrefs();
if (arc_prefs && arc_prefs->IsRegistered(app_id)) {
return true;
}
if (app_id == arc::kPlayStoreAppId) {
if (!arc::IsArcAllowedForProfile(profile()) ||
!arc::IsPlayStoreAvailable()) {
return false;
}
const arc::ArcSessionManager* arc_session_manager =
arc::ArcSessionManager::Get();
DCHECK(arc_session_manager);
if (!arc_session_manager->IsAllowed()) {
return false;
}
if (!arc::IsArcPlayStoreEnabledForProfile(profile()) &&
arc::IsArcPlayStoreEnabledPreferenceManagedForProfile(profile())) {
return false;
}
return true;
}
return false;
}
bool LauncherControllerHelper::IsValidIDFromAppService(
const std::string& app_id) const {
apps::AppServiceProxy* proxy =
apps::AppServiceProxyFactory::GetForProfile(profile_);
if (!proxy) {
return false;
}
apps::mojom::AppType app_type = proxy->AppRegistryCache().GetAppType(app_id);
if (app_type == apps::mojom::AppType::kUnknown ||
app_type == apps::mojom::AppType::kArc) {
return false;
}
return true;
}
...@@ -39,7 +39,7 @@ class LauncherControllerHelper : public ExtensionEnableFlowDelegate { ...@@ -39,7 +39,7 @@ class LauncherControllerHelper : public ExtensionEnableFlowDelegate {
// Returns true if |id| is valid for the currently active profile. // Returns true if |id| is valid for the currently active profile.
// Used during restore to ignore no longer valid extensions. // Used during restore to ignore no longer valid extensions.
// Note that already running applications are ignored by the restore process. // Note that already running applications are ignored by the restore process.
virtual bool IsValidIDForCurrentUser(const std::string& id) const; virtual bool IsValidIDForCurrentUser(const std::string& app_id) const;
void LaunchApp(const ash::ShelfID& id, void LaunchApp(const ash::ShelfID& id,
ash::ShelfLaunchSource source, ash::ShelfLaunchSource source,
...@@ -57,6 +57,13 @@ class LauncherControllerHelper : public ExtensionEnableFlowDelegate { ...@@ -57,6 +57,13 @@ class LauncherControllerHelper : public ExtensionEnableFlowDelegate {
void ExtensionEnableFlowFinished() override; void ExtensionEnableFlowFinished() override;
void ExtensionEnableFlowAborted(bool user_initiated) override; void ExtensionEnableFlowAborted(bool user_initiated) override;
// Returns true if |id| is a valid ARC app for the currently active profile.
bool IsValidIDForArcApp(const std::string& app_id) const;
// Returns true if |id| is a valid app from AppService. ARC app is not
// handled by this method.
bool IsValidIDFromAppService(const std::string& app_id) const;
// The currently active profile for the usage of |GetAppID|. // The currently active profile for the usage of |GetAppID|.
Profile* profile_; Profile* profile_;
std::unique_ptr<ExtensionEnableFlow> extension_enable_flow_; std::unique_ptr<ExtensionEnableFlow> extension_enable_flow_;
......
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