Commit c378a2aa authored by Giovanni Ortuño Urquidi's avatar Giovanni Ortuño Urquidi Committed by Commit Bot

desktop-pwas: Update placeholder apps when we navigate to their urls

1. Adds a method to WebAppPolicyManager to check if we just navigated
   to a URL for a policy app.
2. Adds a method to PendingAppManager to update a placeholder app if
   there is one.
3. Adds code to WebAppTabHelperBase that notifies WebAppPolicyManager
   that a navigation just finished.

Bug: 844278
Change-Id: I9946108092670f3bd86cc3e8aa0d6287eb3dc12e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1552210Reviewed-by: default avatarAlexey Baskakov <loyso@chromium.org>
Commit-Queue: Giovanni Ortuño Urquidi <ortuno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#648667}
parent 1545950b
......@@ -12,6 +12,7 @@
#include "base/values.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/browser/web_applications/bookmark_apps/test_web_app_provider.h"
#include "chrome/browser/web_applications/components/install_options.h"
#include "chrome/browser/web_applications/components/pending_app_manager.h"
#include "chrome/browser/web_applications/components/policy/web_app_policy_constants.h"
#include "chrome/browser/web_applications/components/test_pending_app_manager.h"
......@@ -35,9 +36,9 @@ namespace web_app {
namespace {
const char kWindowedUrl[] = "https://windowed.example";
const char kTabbedUrl[] = "https://tabbed.example";
const char kNoContainerUrl[] = "https://no-container.example";
const char kWindowedUrl[] = "https://windowed.example/";
const char kTabbedUrl[] = "https://tabbed.example/";
const char kNoContainerUrl[] = "https://no-container.example/";
base::Value GetWindowedItem() {
base::Value item(base::Value::Type::DICTIONARY);
......@@ -161,7 +162,7 @@ class WebAppPolicyManagerTest : public ChromeRenderViewHostTestHarness {
return provider;
}
std::string GenerateFakeExtensionId(GURL& url) {
std::string GenerateFakeExtensionId(const GURL& url) {
return crx_file::id_util::GenerateId("fake_app_id_for:" + url.spec());
}
......@@ -383,4 +384,52 @@ TEST_F(WebAppPolicyManagerTest, UninstallAppInstalledInCurrentSession) {
pending_app_manager()->uninstall_requests());
}
// Tests that we correctly reinstall a placeholder app.
TEST_F(WebAppPolicyManagerTest, ReinstallPlaceholderApp) {
base::Value list(base::Value::Type::LIST);
list.GetList().push_back(GetWindowedItem());
profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
policy_manager()->Start();
base::RunLoop().RunUntilIdle();
std::vector<InstallOptions> expected_options_list;
expected_options_list.push_back(GetWindowedInstallOptions());
const auto& install_options_list = pending_app_manager()->install_requests();
EXPECT_EQ(expected_options_list, install_options_list);
policy_manager()->ReinstallPlaceholderAppIfNecessary(GURL(kWindowedUrl));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(expected_options_list, install_options_list);
const auto& reinstall_options_list =
pending_app_manager()->reinstall_requests();
EXPECT_EQ(expected_options_list, reinstall_options_list);
}
TEST_F(WebAppPolicyManagerTest, TryToInexistentPlaceholderApp) {
base::Value list(base::Value::Type::LIST);
list.GetList().push_back(GetWindowedItem());
profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
policy_manager()->Start();
base::RunLoop().RunUntilIdle();
std::vector<InstallOptions> expected_options_list;
expected_options_list.push_back(GetWindowedInstallOptions());
const auto& install_options_list = pending_app_manager()->install_requests();
EXPECT_EQ(expected_options_list, install_options_list);
EXPECT_TRUE(pending_app_manager()->reinstall_requests().empty());
// Try to reinstall for app not installed by policy.
policy_manager()->ReinstallPlaceholderAppIfNecessary(GURL(kTabbedUrl));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(expected_options_list, install_options_list);
EXPECT_TRUE(pending_app_manager()->reinstall_requests().empty());
}
} // namespace web_app
......@@ -74,6 +74,14 @@ class PendingAppManager {
virtual void UninstallApps(std::vector<GURL> uninstall_urls,
const UninstallCallback& callback) = 0;
// If there is a placeholder app for |install_options.url| removes that app
// and tries to install the app again.
// TODO(ortuno): Temporarily use the same callback as Install. We should
// figure out if we want a separate enum for reinstall results or just re-use
// the InstallResult enum for both methods.
virtual void ReinstallPlaceholderApp(InstallOptions install_options,
OnceInstallCallback callback) = 0;
// Returns the URLs of those apps installed from |install_source|.
virtual std::vector<GURL> GetInstalledAppUrls(
InstallSource install_source) const = 0;
......
......@@ -4,13 +4,16 @@
#include "chrome/browser/web_applications/components/policy/web_app_policy_manager.h"
#include <algorithm>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/task/post_task.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/web_applications/components/install_options.h"
#include "chrome/browser/web_applications/components/policy/web_app_policy_constants.h"
#include "chrome/browser/web_applications/components/web_app_constants.h"
#include "chrome/common/pref_names.h"
......@@ -21,6 +24,51 @@
namespace web_app {
namespace {
InstallOptions GetInstallOptionsForPolicyEntry(const base::Value& entry) {
const base::Value& url = *entry.FindKey(kUrlKey);
const base::Value* default_launch_container =
entry.FindKey(kDefaultLaunchContainerKey);
const base::Value* create_desktop_shortcut =
entry.FindKey(kCreateDesktopShorcutKey);
DCHECK(!default_launch_container ||
default_launch_container->GetString() ==
kDefaultLaunchContainerWindowValue ||
default_launch_container->GetString() ==
kDefaultLaunchContainerTabValue);
LaunchContainer launch_container;
if (!default_launch_container) {
launch_container = LaunchContainer::kTab;
} else if (default_launch_container->GetString() ==
kDefaultLaunchContainerTabValue) {
launch_container = LaunchContainer::kTab;
} else {
launch_container = LaunchContainer::kWindow;
}
InstallOptions install_options(GURL(url.GetString()), launch_container,
web_app::InstallSource::kExternalPolicy);
bool create_shortcut = false;
if (create_desktop_shortcut)
create_shortcut = create_desktop_shortcut->GetBool();
install_options.add_to_applications_menu = create_shortcut;
install_options.add_to_desktop = create_shortcut;
// It's not yet clear how pinning to shelf will work for policy installed
// Web Apps, but for now never pin them. See crbug.com/880125.
install_options.add_to_quick_launch_bar = false;
install_options.install_placeholder = true;
return install_options;
}
} // namespace
WebAppPolicyManager::WebAppPolicyManager(Profile* profile,
PendingAppManager* pending_app_manager)
: profile_(profile),
......@@ -39,6 +87,26 @@ void WebAppPolicyManager::Start() {
weak_ptr_factory_.GetWeakPtr()));
}
void WebAppPolicyManager::ReinstallPlaceholderAppIfNecessary(const GURL& url) {
const base::Value* web_apps =
pref_service_->GetList(prefs::kWebAppInstallForceList);
const auto& web_apps_list = web_apps->GetList();
const auto it =
std::find_if(web_apps_list.begin(), web_apps_list.end(),
[&url](const base::Value& entry) {
return entry.FindKey(kUrlKey)->GetString() == url.spec();
});
if (it == web_apps_list.end())
return;
// If the app is not a placeholder app, PendingAppManager will ignore the
// request.
pending_app_manager_->ReinstallPlaceholderApp(
GetInstallOptionsForPolicyEntry(*it), base::DoNothing());
}
// static
void WebAppPolicyManager::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
......@@ -62,46 +130,8 @@ void WebAppPolicyManager::RefreshPolicyInstalledApps() {
// No need to validate the types or values of the policy members because we
// are using a SimpleSchemaValidatingPolicyHandler which should validate them
// for us.
for (const base::Value& info : web_apps->GetList()) {
const base::Value& url = *info.FindKey(kUrlKey);
const base::Value* default_launch_container =
info.FindKey(kDefaultLaunchContainerKey);
const base::Value* create_desktop_shortcut =
info.FindKey(kCreateDesktopShorcutKey);
DCHECK(!default_launch_container ||
default_launch_container->GetString() ==
kDefaultLaunchContainerWindowValue ||
default_launch_container->GetString() ==
kDefaultLaunchContainerTabValue);
LaunchContainer launch_container;
if (!default_launch_container)
launch_container = LaunchContainer::kTab;
else if (default_launch_container->GetString() ==
kDefaultLaunchContainerTabValue)
launch_container = LaunchContainer::kTab;
else
launch_container = LaunchContainer::kWindow;
InstallOptions install_options(GURL(std::move(url.GetString())),
launch_container,
web_app::InstallSource::kExternalPolicy);
bool create_shortcut = false;
if (create_desktop_shortcut)
create_shortcut = create_desktop_shortcut->GetBool();
install_options.add_to_applications_menu = create_shortcut;
install_options.add_to_desktop = create_shortcut;
// It's not yet clear how pinning to shelf will work for policy installed
// Web Apps, but for now never pin them. See crbug.com/880125.
install_options.add_to_quick_launch_bar = false;
install_options.install_placeholder = true;
install_options_list.push_back(std::move(install_options));
for (const base::Value& entry : web_apps->GetList()) {
install_options_list.push_back(GetInstallOptionsForPolicyEntry(entry));
}
pending_app_manager_->SynchronizeInstalledApps(
......
......@@ -35,6 +35,8 @@ class WebAppPolicyManager {
void Start();
void ReinstallPlaceholderAppIfNecessary(const GURL& url);
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
private:
......
......@@ -72,6 +72,14 @@ void TestPendingAppManager::UninstallApps(std::vector<GURL> uninstall_urls,
}
}
void TestPendingAppManager::ReinstallPlaceholderApp(
InstallOptions install_options,
OnceInstallCallback callback) {
reinstall_requests_.push_back(std::move(install_options));
std::move(callback).Run(reinstall_requests_.back().url,
InstallResultCode::kSuccess);
}
std::vector<GURL> TestPendingAppManager::GetInstalledAppUrls(
InstallSource install_source) const {
std::vector<GURL> urls;
......
......@@ -30,6 +30,9 @@ class TestPendingAppManager : public PendingAppManager {
const std::vector<GURL>& uninstall_requests() const {
return uninstall_requests_;
}
const std::vector<InstallOptions>& reinstall_requests() const {
return reinstall_requests_;
}
int deduped_install_count() const { return deduped_install_count_; }
int deduped_uninstall_count() const { return deduped_uninstall_count_; }
......@@ -49,6 +52,8 @@ class TestPendingAppManager : public PendingAppManager {
const RepeatingInstallCallback& callback) override;
void UninstallApps(std::vector<GURL> uninstall_urls,
const UninstallCallback& callback) override;
void ReinstallPlaceholderApp(InstallOptions install_options,
OnceInstallCallback callback) override;
std::vector<GURL> GetInstalledAppUrls(
InstallSource install_source) const override;
base::Optional<std::string> LookupAppId(const GURL& url) const override;
......@@ -57,6 +62,7 @@ class TestPendingAppManager : public PendingAppManager {
void DoInstall(InstallOptions install_options, OnceInstallCallback callback);
std::vector<InstallOptions> install_requests_;
std::vector<GURL> uninstall_requests_;
std::vector<InstallOptions> reinstall_requests_;
int deduped_install_count_;
int deduped_uninstall_count_;
......
......@@ -5,7 +5,10 @@
#include "chrome/browser/web_applications/components/web_app_tab_helper_base.h"
#include "base/unguessable_token.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/web_applications/components/policy/web_app_policy_manager.h"
#include "chrome/browser/web_applications/components/web_app_audio_focus_id_map.h"
#include "chrome/browser/web_applications/components/web_app_provider_base.h"
#include "content/public/browser/media_session.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/site_instance.h"
......@@ -48,6 +51,8 @@ void WebAppTabHelperBase::DidFinishNavigation(
const AppId app_id = FindAppIdInScopeOfUrl(navigation_handle->GetURL());
SetAppId(app_id);
ReinstallPlaceholderAppIfNecessary(navigation_handle->GetURL());
}
void WebAppTabHelperBase::DidCloneToNewWebContents(
......@@ -98,4 +103,16 @@ void WebAppTabHelperBase::UpdateAudioFocusGroupId() {
->SetAudioFocusGroupId(audio_focus_group_id_);
}
void WebAppTabHelperBase::ReinstallPlaceholderAppIfNecessary(const GURL& url) {
auto* provider = web_app::WebAppProviderBase::GetProviderBase(
Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
DCHECK(provider);
// WebAppPolicyManager might be nullptr in the non-extensions implementation.
if (!provider->policy_manager())
return;
provider->policy_manager()->ReinstallPlaceholderAppIfNecessary(url);
}
} // namespace web_app
......@@ -87,6 +87,9 @@ class WebAppTabHelperBase
// Updates the audio focus group id based on the current web app.
void UpdateAudioFocusGroupId();
// Triggers a reinstall of a placeholder app for |url|.
void ReinstallPlaceholderAppIfNecessary(const GURL& url);
// WebApp associated with this tab. Empty string if no app associated.
AppId app_id_;
......
......@@ -93,6 +93,38 @@ void PendingBookmarkAppManager::UninstallApps(
}
}
void PendingBookmarkAppManager::ReinstallPlaceholderApp(
web_app::InstallOptions install_options,
OnceInstallCallback callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&PendingBookmarkAppManager::StartReinstallTask,
weak_ptr_factory_.GetWeakPtr(), std::move(install_options),
std::move(callback)));
}
void PendingBookmarkAppManager::StartReinstallTask(
web_app::InstallOptions install_options,
OnceInstallCallback callback) {
base::Optional<std::string> extension_id =
extension_ids_map_.LookupPlaceholderAppId(install_options.url);
bool uninstall_succeeded = true;
if (extension_id.has_value() &&
registrar_->IsInstalled(extension_id.value())) {
uninstall_succeeded = uninstaller_->UninstallApp(install_options.url);
}
if (!uninstall_succeeded) {
LOG(WARNING) << "Could not uninstall Web App for : " << install_options.url;
std::move(callback).Run(install_options.url,
web_app::InstallResultCode::kFailedUnknownReason);
return;
}
Install(std::move(install_options), std::move(callback));
}
std::vector<GURL> PendingBookmarkAppManager::GetInstalledAppUrls(
web_app::InstallSource install_source) const {
return web_app::ExtensionIdsMap::GetInstalledAppUrls(profile_,
......
......@@ -63,6 +63,8 @@ class PendingBookmarkAppManager final : public web_app::PendingAppManager {
const RepeatingInstallCallback& callback) override;
void UninstallApps(std::vector<GURL> uninstall_urls,
const UninstallCallback& callback) override;
void ReinstallPlaceholderApp(web_app::InstallOptions install_options,
OnceInstallCallback callback) override;
std::vector<GURL> GetInstalledAppUrls(
web_app::InstallSource install_source) const override;
base::Optional<std::string> LookupAppId(const GURL& url) const override;
......@@ -80,6 +82,9 @@ class PendingBookmarkAppManager final : public web_app::PendingAppManager {
void StartInstallationTask(std::unique_ptr<TaskAndCallback> task);
void StartReinstallTask(web_app::InstallOptions install_options,
OnceInstallCallback callback);
void CreateWebContentsIfNecessary();
void OnUrlLoaded(web_app::WebAppUrlLoader::Result result);
......
......@@ -105,7 +105,7 @@ class TestBookmarkAppInstallationTask : public BookmarkAppInstallationTask {
BookmarkAppInstallationTask::ResultCallback callback) override {
std::move(on_install_placeholder_called_).Run();
if (succeeds_) {
std::move(callback).Run(SimulateInstallingApp());
std::move(callback).Run(SimulateInstallingApp(true /* is_placeholder */));
} else {
std::move(callback).Run(BookmarkAppInstallationTask::Result(
web_app::InstallResultCode::kFailedUnknownReason, std::string()));
......@@ -122,10 +122,12 @@ class TestBookmarkAppInstallationTask : public BookmarkAppInstallationTask {
}
private:
BookmarkAppInstallationTask::Result SimulateInstallingApp() {
BookmarkAppInstallationTask::Result SimulateInstallingApp(
bool is_placeholder = false) {
std::string app_id = GenerateFakeAppId(install_options().url);
extension_ids_map_.Insert(install_options().url, app_id,
install_options().install_source);
extension_ids_map_.SetIsPlaceholder(install_options().url, is_placeholder);
registrar_->AddAsInstalled(app_id);
return {web_app::InstallResultCode::kSuccess, app_id};
}
......@@ -143,8 +145,9 @@ class TestBookmarkAppInstallationTask : public BookmarkAppInstallationTask {
class TestBookmarkAppUninstaller : public BookmarkAppUninstaller {
public:
TestBookmarkAppUninstaller(Profile* profile, web_app::AppRegistrar* registrar)
: BookmarkAppUninstaller(profile, registrar) {}
TestBookmarkAppUninstaller(Profile* profile,
web_app::TestAppRegistrar* registrar)
: BookmarkAppUninstaller(profile, registrar), registrar_(registrar) {}
~TestBookmarkAppUninstaller() override = default;
......@@ -170,11 +173,16 @@ class TestBookmarkAppUninstaller : public BookmarkAppUninstaller {
bool result = next_result_map_[app_url];
next_result_map_.erase(app_url);
if (result)
registrar_->RemoveAsInstalled(GenerateFakeAppId(app_url));
return result;
}
private:
std::map<GURL, bool> next_result_map_;
web_app::TestAppRegistrar* registrar_;
size_t uninstall_call_count_ = 0;
std::vector<GURL> uninstalled_app_urls_;
......@@ -269,6 +277,28 @@ class PendingBookmarkAppManagerTest : public ChromeRenderViewHostTestHarness {
return {url.value(), code.value()};
}
std::pair<GURL, web_app::InstallResultCode> ReinstallPlaceholderAppAndWait(
web_app::PendingAppManager* pending_app_manager,
web_app::InstallOptions install_options) {
base::RunLoop run_loop;
base::Optional<GURL> url;
base::Optional<web_app::InstallResultCode> code;
pending_app_manager->ReinstallPlaceholderApp(
std::move(install_options),
base::BindLambdaForTesting(
[&](const GURL& app_url,
web_app::InstallResultCode install_result_code) {
url = app_url;
code = install_result_code;
run_loop.Quit();
}));
run_loop.Run();
return {url.value(), code.value()};
}
std::vector<std::pair<GURL, web_app::InstallResultCode>> InstallAppsAndWait(
web_app::PendingAppManager* pending_app_manager,
std::vector<web_app::InstallOptions> apps_to_install) {
......@@ -1100,6 +1130,7 @@ TEST_F(PendingBookmarkAppManagerTest, ExternalExtensionUninstalled) {
TEST_F(PendingBookmarkAppManagerTest, UninstallApps_Succeeds) {
auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
registrar()->AddAsInstalled(GenerateFakeAppId(GURL(kFooWebAppUrl)));
uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true);
UninstallAppsResults results = UninstallAppsAndWait(
......@@ -1125,6 +1156,8 @@ TEST_F(PendingBookmarkAppManagerTest, UninstallApps_Fails) {
TEST_F(PendingBookmarkAppManagerTest, UninstallApps_Multiple) {
auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
registrar()->AddAsInstalled(GenerateFakeAppId(GURL(kFooWebAppUrl)));
registrar()->AddAsInstalled(GenerateFakeAppId(GURL(kBarWebAppUrl)));
uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true);
uninstaller()->SetNextResultForTesting(GURL(kBarWebAppUrl), true);
......@@ -1164,4 +1197,133 @@ TEST_F(PendingBookmarkAppManagerTest, UninstallApps_PendingInstall) {
run_loop.Run();
}
TEST_F(PendingBookmarkAppManagerTest, ReinstallPlaceholderApp_Success) {
auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
// Install a placeholder app
auto install_options = GetFooInstallOptions();
install_options.install_placeholder = true;
{
url_loader()->SetNextLoadUrlResult(
GURL(kFooWebAppUrl),
web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
base::Optional<GURL> url;
base::Optional<web_app::InstallResultCode> code;
std::tie(url, code) =
InstallAndWait(pending_app_manager.get(), install_options);
ASSERT_EQ(web_app::InstallResultCode::kSuccess, code.value());
EXPECT_EQ(0u, install_run_count());
EXPECT_EQ(1u, install_placeholder_run_count());
}
// Reinstall placeholder
{
url_loader()->SetNextLoadUrlResult(
GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true);
base::Optional<GURL> url;
base::Optional<web_app::InstallResultCode> code;
std::tie(url, code) = ReinstallPlaceholderAppAndWait(
pending_app_manager.get(), install_options);
EXPECT_EQ(web_app::InstallResultCode::kSuccess, code.value());
EXPECT_EQ(GURL(kFooWebAppUrl), url.value());
EXPECT_EQ(1u, uninstall_call_count());
EXPECT_EQ(GURL(kFooWebAppUrl), last_uninstalled_app_url());
EXPECT_EQ(1u, install_run_count());
EXPECT_EQ(1u, install_placeholder_run_count());
}
}
TEST_F(PendingBookmarkAppManagerTest,
ReinstallPlaceholderApp_FailsToUninstall) {
auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
// Install a placeholder app
auto install_options = GetFooInstallOptions();
install_options.install_placeholder = true;
{
url_loader()->SetNextLoadUrlResult(
GURL(kFooWebAppUrl),
web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
base::Optional<GURL> url;
base::Optional<web_app::InstallResultCode> code;
std::tie(url, code) =
InstallAndWait(pending_app_manager.get(), install_options);
ASSERT_EQ(web_app::InstallResultCode::kSuccess, code.value());
EXPECT_EQ(0u, install_run_count());
EXPECT_EQ(1u, install_placeholder_run_count());
}
// Reinstall placeholder
{
url_loader()->SetNextLoadUrlResult(
GURL(kFooWebAppUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), false);
base::Optional<GURL> url;
base::Optional<web_app::InstallResultCode> code;
std::tie(url, code) = ReinstallPlaceholderAppAndWait(
pending_app_manager.get(), install_options);
EXPECT_EQ(web_app::InstallResultCode::kFailedUnknownReason, code.value());
EXPECT_EQ(GURL(kFooWebAppUrl), url.value());
EXPECT_EQ(1u, uninstall_call_count());
EXPECT_EQ(GURL(kFooWebAppUrl), last_uninstalled_app_url());
EXPECT_EQ(0u, install_run_count());
EXPECT_EQ(1u, install_placeholder_run_count());
}
}
TEST_F(PendingBookmarkAppManagerTest,
ReinstallPlaceholderApp_ReinstallNotPossible) {
auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories();
// Install a placeholder app
auto install_options = GetFooInstallOptions();
install_options.install_placeholder = true;
{
url_loader()->SetNextLoadUrlResult(
GURL(kFooWebAppUrl),
web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
base::Optional<GURL> url;
base::Optional<web_app::InstallResultCode> code;
std::tie(url, code) =
InstallAndWait(pending_app_manager.get(), install_options);
ASSERT_EQ(web_app::InstallResultCode::kSuccess, code.value());
EXPECT_EQ(0u, install_run_count());
EXPECT_EQ(1u, install_placeholder_run_count());
}
// Reinstall placeholder
{
url_loader()->SetNextLoadUrlResult(
GURL(kFooWebAppUrl),
web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded);
uninstaller()->SetNextResultForTesting(GURL(kFooWebAppUrl), true);
base::Optional<GURL> url;
base::Optional<web_app::InstallResultCode> code;
std::tie(url, code) = ReinstallPlaceholderAppAndWait(
pending_app_manager.get(), install_options);
EXPECT_EQ(web_app::InstallResultCode::kSuccess, code.value());
EXPECT_EQ(GURL(kFooWebAppUrl), url.value());
EXPECT_EQ(1u, uninstall_call_count());
EXPECT_EQ(GURL(kFooWebAppUrl), last_uninstalled_app_url());
EXPECT_EQ(0u, install_run_count());
EXPECT_EQ(2u, install_placeholder_run_count());
}
}
} // namespace extensions
......@@ -178,6 +178,23 @@ base::Optional<std::string> ExtensionIdsMap::LookupExtensionId(
return base::nullopt;
}
base::Optional<std::string> ExtensionIdsMap::LookupPlaceholderAppId(
const GURL& url) const {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
const base::Value* entry =
pref_service_->GetDictionary(prefs::kWebAppsExtensionIDs)
->FindKey(url.spec());
if (!entry)
return base::nullopt;
base::Optional<bool> is_placeholder = entry->FindBoolKey(kIsPlaceholder);
if (!is_placeholder.has_value() || !is_placeholder.value())
return base::nullopt;
return *entry->FindStringKey(kExtensionId);
}
void ExtensionIdsMap::SetIsPlaceholder(const GURL& url, bool is_placeholder) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
......
......@@ -50,6 +50,11 @@ class ExtensionIdsMap {
const std::string& extension_id,
InstallSource install_source);
base::Optional<std::string> LookupExtensionId(const GURL& url) const;
// Returns an id if there is a placeholder app for |url|. Note that nullopt
// does not mean that there is no app for |url| just that there is no
// *placeholder app*.
base::Optional<std::string> LookupPlaceholderAppId(const GURL& url) const;
void SetIsPlaceholder(const GURL& url, bool is_placeholder);
private:
......
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