Commit 463f114b authored by Wenzhao Zang's avatar Wenzhao Zang Committed by Commit Bot

cros: Install Highlights app from update url and enable app caching

We should try to install the Highlights app from the update url in
the two cases:

1) Offline enrollment, but offline resources are not available for any
   reason (should be a bug if it ever happens).
2) Online enrollment (will do in a follow-up CL).

In addition, enable app caching so that Highlights app can be launched
in cases when device is offline (but was once enrolled online).
Besides, the correct version of Highlights app can be determined
dynamically, so only one copy will be downloaded/cached to save
bandwidth and disk space.

Bug: 819404
Change-Id: Ia3b6d8d5222411474b106e1871bfbac6f0c755e5
Reviewed-on: https://chromium-review.googlesource.com/1194337Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Reviewed-by: default avatarMichael Giuffrida <michaelpg@chromium.org>
Commit-Queue: Wenzhao (Colin) Zang <wzang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#589042}
parent 085697fe
......@@ -4,21 +4,25 @@
#include "chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.h"
#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/optional.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/extensions/external_cache_impl.h"
#include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/extensions/external_provider_impl.h"
#include "extensions/browser/extension_file_task_runner.h"
#include "extensions/common/extension_urls.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace chromeos {
......@@ -67,19 +71,57 @@ bool DemoExtensionsExternalLoader::SupportedForProfile(Profile* profile) {
return demo_session && demo_session->started();
}
DemoExtensionsExternalLoader::DemoExtensionsExternalLoader()
: weak_ptr_factory_(this) {
DemoExtensionsExternalLoader::DemoExtensionsExternalLoader(
const base::FilePath& cache_dir)
: cache_dir_(cache_dir), weak_ptr_factory_(this) {
DCHECK(DemoSession::Get() && DemoSession::Get()->started());
}
DemoExtensionsExternalLoader::~DemoExtensionsExternalLoader() = default;
void DemoExtensionsExternalLoader::LoadApp(const std::string& app_id) {
base::DictionaryValue prefs;
base::DictionaryValue app_dict;
app_dict.SetKey(extensions::ExternalProviderImpl::kExternalUpdateUrl,
base::Value(extension_urls::kChromeWebstoreUpdateURL));
prefs.SetKey(app_id, std::move(app_dict));
if (!external_cache_) {
external_cache_ = std::make_unique<ExternalCacheImpl>(
cache_dir_, g_browser_process->shared_url_loader_factory(),
extensions::GetExtensionFileTaskRunner(), this,
true /* always_check_updates */,
false /* wait_for_cache_initialization */);
}
external_cache_->UpdateExtensionsList(base::DictionaryValue::From(
base::Value::ToUniquePtrValue(std::move(prefs))));
}
void DemoExtensionsExternalLoader::StartLoading() {
DemoSession::Get()->EnsureOfflineResourcesLoaded(base::BindOnce(
&DemoExtensionsExternalLoader::StartLoadingFromOfflineDemoResources,
weak_ptr_factory_.GetWeakPtr()));
}
void DemoExtensionsExternalLoader::OnExtensionListsUpdated(
const base::DictionaryValue* prefs) {
DCHECK(external_cache_);
// Notifies the provider that the extensions have either been downloaded or
// found in cache, and are ready to be installed.
LoadFinished(prefs->CreateDeepCopy());
}
void DemoExtensionsExternalLoader::OnExtensionLoadedInCache(
const std::string& id) {}
void DemoExtensionsExternalLoader::OnExtensionDownloadFailed(
const std::string& id) {}
std::string DemoExtensionsExternalLoader::GetInstalledExtensionVersion(
const std::string& id) {
return std::string();
}
void DemoExtensionsExternalLoader::StartLoadingFromOfflineDemoResources() {
DemoSession* demo_session = DemoSession::Get();
DCHECK(demo_session->offline_resources_loaded());
......
......@@ -5,9 +5,14 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_EXTENSIONS_EXTERNAL_LOADER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_EXTENSIONS_EXTERNAL_LOADER_H_
#include <memory>
#include <string>
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "chrome/browser/chromeos/extensions/external_cache_delegate.h"
#include "chrome/browser/extensions/external_loader.h"
class Profile;
......@@ -18,6 +23,8 @@ class Value;
namespace chromeos {
class ExternalCache;
// External loader for extensions to be loaded into demo mode sessions. The CRX
// files are loaded from preinstalled demo mode resources image mounted by
// image loader service (from the device's stateful partition).
......@@ -26,17 +33,27 @@ namespace chromeos {
// mounted demo resources root to absolute paths that can be used by external
// extensions provider.
// NOTE: The class is expected to be used on the UI thread exclusively.
class DemoExtensionsExternalLoader : public extensions::ExternalLoader {
class DemoExtensionsExternalLoader : public extensions::ExternalLoader,
public ExternalCacheDelegate {
public:
// Whether demo apps should be loaded for the profile - i.e. whether the
// profile is the primary profile in a demo session.
static bool SupportedForProfile(Profile* profile);
DemoExtensionsExternalLoader();
explicit DemoExtensionsExternalLoader(const base::FilePath& cache_dir);
// Loads the app with |app_id| and installs it from the update url or cache.
void LoadApp(const std::string& app_id);
// extensions::ExternalLoader:
void StartLoading() override;
// ExternalCacheDelegate:
void OnExtensionListsUpdated(const base::DictionaryValue* prefs) override;
void OnExtensionLoadedInCache(const std::string& id) override;
void OnExtensionDownloadFailed(const std::string& id) override;
std::string GetInstalledExtensionVersion(const std::string& id) override;
protected:
~DemoExtensionsExternalLoader() override;
......@@ -50,6 +67,10 @@ class DemoExtensionsExternalLoader : public extensions::ExternalLoader {
// |prefs| - demo extensions prefs.
void DemoExternalExtensionsPrefsLoaded(base::Optional<base::Value> prefs);
std::unique_ptr<ExternalCache> external_cache_;
const base::FilePath cache_dir_;
base::WeakPtrFactory<DemoExtensionsExternalLoader> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DemoExtensionsExternalLoader);
......
......@@ -18,22 +18,30 @@
#include "base/json/json_writer.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/extensions/external_provider_impl.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_image_loader_client.h"
#include "components/session_manager/core/session_manager.h"
#include "components/user_manager/scoped_user_manager.h"
#include "content/public/browser/notification_service.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/external_install_info.h"
#include "extensions/browser/external_provider_interface.h"
#include "extensions/browser/notification_types.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
......@@ -43,6 +51,13 @@ namespace {
// Information about found external extension file: {version, crx_path}.
using TestCrxInfo = std::tuple<std::string, std::string>;
constexpr char kTestExtensionId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
constexpr char kTestExtensionUpdateManifest[] =
"extensions/good_v1_update_manifest.xml";
constexpr char kTestExtensionCRXVersion[] = "1.0.0.0";
class TestExternalProviderVisitor
: public extensions::ExternalProviderInterface::VisitorInterface {
public:
......@@ -61,6 +76,16 @@ class TestExternalProviderVisitor
ready_waiter_.reset();
}
void WaitForFileFound() {
if (!loaded_crx_files_.empty())
return;
file_waiter_ = std::make_unique<base::RunLoop>();
file_waiter_->Run();
file_waiter_.reset();
}
void ClearLoadedFiles() { loaded_crx_files_.clear(); }
// extensions::ExternalProviderInterface::VisitorInterface:
bool OnExternalExtensionFileFound(
const extensions::ExternalInstallInfoFile& info) override {
......@@ -71,14 +96,15 @@ class TestExternalProviderVisitor
loaded_crx_files_.emplace(
info.extension_id,
TestCrxInfo(info.version.GetString(), info.path.value()));
if (file_waiter_)
file_waiter_->Quit();
return true;
}
bool OnExternalExtensionUpdateUrlFound(
const extensions::ExternalInstallInfoUpdateUrl& info,
bool is_initial_load) override {
ADD_FAILURE() << "Found extensions with update URL";
return false;
return true;
}
void OnExternalProviderReady(
......@@ -99,10 +125,13 @@ class TestExternalProviderVisitor
private:
bool ready_ = false;
std::map<std::string, TestCrxInfo> loaded_crx_files_;
std::unique_ptr<base::RunLoop> ready_waiter_;
std::unique_ptr<base::RunLoop> file_waiter_;
DISALLOW_COPY_AND_ASSIGN(TestExternalProviderVisitor);
};
......@@ -110,7 +139,11 @@ class TestExternalProviderVisitor
class DemoExtensionsExternalLoaderTest : public testing::Test {
public:
DemoExtensionsExternalLoaderTest() = default;
DemoExtensionsExternalLoaderTest()
: test_shared_loader_factory_(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_)) {}
~DemoExtensionsExternalLoaderTest() override = default;
void SetUp() override {
......@@ -123,6 +156,9 @@ class DemoExtensionsExternalLoaderTest : public testing::Test {
DBusThreadManager::GetSetterForTesting()->SetImageLoaderClient(
std::move(image_loader_client));
session_manager_ = std::make_unique<session_manager::SessionManager>();
TestingBrowserProcess::GetGlobal()->SetSharedURLLoaderFactory(
test_shared_loader_factory_);
}
void TearDown() override {
......@@ -193,7 +229,9 @@ class DemoExtensionsExternalLoaderTest : public testing::Test {
std::unique_ptr<extensions::ExternalProviderImpl> CreateExternalProvider(
extensions::ExternalProviderInterface::VisitorInterface* visitor) {
return std::make_unique<extensions::ExternalProviderImpl>(
visitor, base::MakeRefCounted<DemoExtensionsExternalLoader>(),
visitor,
base::MakeRefCounted<DemoExtensionsExternalLoader>(
base::FilePath() /*cache_dir*/),
profile_.get(), extensions::Manifest::INTERNAL,
extensions::Manifest::INTERNAL,
extensions::Extension::FROM_WEBSTORE |
......@@ -203,11 +241,13 @@ class DemoExtensionsExternalLoaderTest : public testing::Test {
protected:
TestExternalProviderVisitor external_provider_visitor_;
std::unique_ptr<TestingProfile> profile_;
network::TestURLLoaderFactory test_url_loader_factory_;
private:
content::TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<TestingProfile> profile_;
// Image loader client injected into, and owned by DBusThreadManager.
FakeImageLoaderClient* image_loader_client_ = nullptr;
......@@ -215,6 +255,11 @@ class DemoExtensionsExternalLoaderTest : public testing::Test {
std::unique_ptr<session_manager::SessionManager> session_manager_;
scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
test_shared_loader_factory_;
content::InProcessUtilityThreadHelper in_process_utility_thread_helper_;
DISALLOW_COPY_AND_ASSIGN(DemoExtensionsExternalLoaderTest);
};
......@@ -439,6 +484,75 @@ TEST_F(DemoExtensionsExternalLoaderTest,
EXPECT_TRUE(external_provider_visitor_.loaded_crx_files().empty());
}
TEST_F(DemoExtensionsExternalLoaderTest, LoadApp) {
InitializeSession(true /*mount_demo_resources*/,
true /*wait_for_offline_resources_load*/);
// Create a temporary cache directory.
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath cache_dir = temp_dir.GetPath().Append("cache");
ASSERT_TRUE(base::CreateDirectoryAndGetError(cache_dir, nullptr /*error*/));
scoped_refptr<chromeos::DemoExtensionsExternalLoader> loader =
base::MakeRefCounted<chromeos::DemoExtensionsExternalLoader>(cache_dir);
std::unique_ptr<extensions::ExternalProviderImpl> external_provider =
std::make_unique<extensions::ExternalProviderImpl>(
&external_provider_visitor_, loader, profile_.get(),
extensions::Manifest::INTERNAL,
extensions::Manifest::EXTERNAL_PREF_DOWNLOAD,
extensions::Extension::FROM_WEBSTORE |
extensions::Extension::WAS_INSTALLED_BY_DEFAULT);
external_provider->VisitRegisteredExtension();
external_provider_visitor_.WaitForReady();
EXPECT_TRUE(external_provider->IsReady());
loader->LoadApp(kTestExtensionId);
// Verify that a downloader has started and is attempting to download an
// update manifest.
EXPECT_EQ(1, test_url_loader_factory_.NumPending());
// Return a manifest to the downloader.
std::string manifest;
base::FilePath test_dir;
ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
EXPECT_TRUE(base::ReadFileToString(
test_dir.Append(kTestExtensionUpdateManifest), &manifest));
EXPECT_EQ(1u, test_url_loader_factory_.pending_requests()->size());
test_url_loader_factory_.AddResponse(
test_url_loader_factory_.pending_requests()->at(0).request.url.spec(),
manifest);
// Wait for the manifest to be parsed.
content::WindowedNotificationObserver(
extensions::NOTIFICATION_EXTENSION_UPDATE_FOUND,
content::NotificationService::AllSources())
.Wait();
// Verify that the downloader is attempting to download a CRX file.
EXPECT_EQ(1u, test_url_loader_factory_.pending_requests()->size());
// Trigger downloading of the CRX file.
test_url_loader_factory_.AddResponse(
test_url_loader_factory_.pending_requests()->at(0).request.url.spec(),
"Dummy content.");
// Verify that the CRX file exists in the cache directory.
external_provider_visitor_.WaitForFileFound();
const base::FilePath cached_crx_path = cache_dir.Append(base::StringPrintf(
"%s-%s.crx", kTestExtensionId, kTestExtensionCRXVersion));
const std::map<std::string, TestCrxInfo> expected_info = {
{kTestExtensionId,
TestCrxInfo(kTestExtensionCRXVersion, cached_crx_path.value())}};
EXPECT_EQ(expected_info, external_provider_visitor_.loaded_crx_files());
// Verify that loading the app again succeeds without downloading.
test_url_loader_factory_.ClearResponses();
external_provider_visitor_.ClearLoadedFiles();
loader->LoadApp(kTestExtensionId);
external_provider_visitor_.WaitForFileFound();
EXPECT_EQ(expected_info, external_provider_visitor_.loaded_crx_files());
}
class ShouldCreateDemoExtensionsExternalLoaderTest : public testing::Test {
public:
ShouldCreateDemoExtensionsExternalLoaderTest() {
......
......@@ -13,6 +13,7 @@
#include "base/files/file_util.h"
#include "base/optional.h"
#include "base/path_service.h"
#include "base/sys_info.h"
#include "base/task/post_task.h"
#include "chrome/browser/apps/platform_apps/app_load_service.h"
#include "chrome/browser/browser_process.h"
......@@ -22,7 +23,10 @@
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/settings/install_attributes.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/extensions/app_launch_params.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/pref_names.h"
#include "chromeos/chromeos_paths.h"
#include "chromeos/dbus/dbus_thread_manager.h"
......@@ -30,6 +34,7 @@
#include "components/prefs/pref_service.h"
#include "components/session_manager/core/session_manager.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/constants.h"
#include "net/base/network_change_notifier.h"
......@@ -62,6 +67,10 @@ constexpr char kHighlightsAppPath[] = "chrome_apps/highlights";
// contains sample photos.
constexpr char kPhotosPath[] = "media/photos";
constexpr char kDefaultHighlightsAppId[] = "lpmakjfjcconjeehbidjclhdlpjmfjjj";
constexpr char kEveHighlightsAppId[] = "iggildboghmjpbjcpmobahnkmoefkike";
bool IsDemoModeOfflineEnrolled() {
DCHECK(DemoSession::IsDeviceInDemoMode());
return DemoSession::GetDemoConfig() == DemoSession::DemoModeConfig::kOffline;
......@@ -96,6 +105,19 @@ void InstallDemoMedia(base::FilePath offline_resources_path) {
LOG(ERROR) << "Failed to install demo mode media.";
}
std::string GetBoardName() {
const std::vector<std::string> board =
base::SplitString(base::SysInfo::GetLsbReleaseBoard(), "-",
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
return board[0];
}
std::string GetHighlightsAppId() {
if (GetBoardName() == "eve")
return kEveHighlightsAppId;
return kDefaultHighlightsAppId;
}
} // namespace
// static
......@@ -303,6 +325,7 @@ DemoSession::DemoSession()
: offline_enrolled_(IsDemoModeOfflineEnrolled()),
ignore_pin_policy_offline_apps_(GetIgnorePinPolicyApps()),
session_manager_observer_(this),
extension_registry_observer_(this),
weak_ptr_factory_(this) {
session_manager_observer_.Add(session_manager::SessionManager::Get());
OnSessionStateChanged();
......@@ -351,6 +374,7 @@ void DemoSession::LoadAndLaunchHighlightsApp() {
DCHECK(offline_resources_loaded_);
if (offline_resources_path_.empty()) {
LOG(ERROR) << "Offline resources not loaded - no highlights app available.";
InstallHighlightsAppFromUpdateUrl();
return;
}
Profile* profile = ProfileManager::GetPrimaryUserProfile();
......@@ -360,10 +384,20 @@ void DemoSession::LoadAndLaunchHighlightsApp() {
if (!apps::AppLoadService::Get(profile)->LoadAndLaunch(
resources_path, base::CommandLine(base::CommandLine::NO_PROGRAM),
base::FilePath() /* cur_dir */)) {
LOG(WARNING) << "Failed to launch highlights app!";
LOG(WARNING) << "Failed to launch highlights app from offline resources.";
InstallHighlightsAppFromUpdateUrl();
}
}
void DemoSession::InstallHighlightsAppFromUpdateUrl() {
if (!extensions_external_loader_)
return;
Profile* profile = ProfileManager::GetPrimaryUserProfile();
DCHECK(profile);
extension_registry_observer_.Add(extensions::ExtensionRegistry::Get(profile));
extensions_external_loader_->LoadApp(GetHighlightsAppId());
}
void DemoSession::OnSessionStateChanged() {
if (session_manager::SessionManager::Get()->session_state() !=
session_manager::SessionState::ACTIVE ||
......@@ -374,4 +408,16 @@ void DemoSession::OnSessionStateChanged() {
&DemoSession::InstallDemoResources, weak_ptr_factory_.GetWeakPtr()));
}
void DemoSession::OnExtensionInstalled(content::BrowserContext* browser_context,
const extensions::Extension* extension,
bool is_update) {
if (extension->id() != GetHighlightsAppId())
return;
Profile* profile = ProfileManager::GetPrimaryUserProfile();
DCHECK(profile);
OpenApplication(AppLaunchParams(
profile, extension, extensions::LAUNCH_CONTAINER_WINDOW,
WindowOpenDisposition::NEW_WINDOW, extensions::SOURCE_CHROME_INTERNAL));
}
} // namespace chromeos
......@@ -12,11 +12,14 @@
#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/scoped_observer.h"
#include "chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.h"
#include "chrome/browser/component_updater/cros_component_installer_chromeos.h"
#include "components/session_manager/core/session_manager_observer.h"
#include "extensions/browser/extension_registry_observer.h"
namespace session_manager {
class SessionManager;
......@@ -26,7 +29,8 @@ namespace chromeos {
// Tracks global demo session state. For example, whether the demo session has
// started, and whether the demo session offline resources have been loaded.
class DemoSession : public session_manager::SessionManagerObserver {
class DemoSession : public session_manager::SessionManagerObserver,
extensions::ExtensionRegistryObserver {
public:
// Type of demo mode configuration.
// Warning: DemoModeConfig is stored in local state. Existing entries should
......@@ -119,6 +123,11 @@ class DemoSession : public session_manager::SessionManagerObserver {
bool offline_resources_loaded() const { return offline_resources_loaded_; }
void set_extensions_external_loader(
scoped_refptr<DemoExtensionsExternalLoader> extensions_external_loader) {
extensions_external_loader_ = extensions_external_loader;
}
private:
DemoSession();
~DemoSession() override;
......@@ -139,12 +148,22 @@ class DemoSession : public session_manager::SessionManagerObserver {
// as apps and media.
void InstallDemoResources();
// Loads and launches the highlights app.
// Loads the highlights app from offline resources and launches it upon
// success.
void LoadAndLaunchHighlightsApp();
// Installs the CRX file from an update URL. Observes |ExtensionRegistry| to
// launch the highlights app upon installation.
void InstallHighlightsAppFromUpdateUrl();
// session_manager::SessionManagerObserver:
void OnSessionStateChanged() override;
// extensions::ExtensionRegistryObserver:
void OnExtensionInstalled(content::BrowserContext* browser_context,
const extensions::Extension* extension,
bool is_update) override;
// Whether the device was offline-enrolled into demo mode, i.e. enrolled using
// pre-built policies. Offline enrolled demo sessions do not have working
// robot account associated with them.
......@@ -169,6 +188,12 @@ class DemoSession : public session_manager::SessionManagerObserver {
session_manager::SessionManagerObserver>
session_manager_observer_;
ScopedObserver<extensions::ExtensionRegistry,
extensions::ExtensionRegistryObserver>
extension_registry_observer_;
scoped_refptr<DemoExtensionsExternalLoader> extensions_external_loader_;
base::WeakPtrFactory<DemoSession> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DemoSession);
......
......@@ -48,14 +48,17 @@
#include "ui/base/l10n/l10n_util.h"
#if defined(OS_CHROMEOS)
#include "base/path_service.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_external_loader.h"
#include "chrome/browser/chromeos/customization/customization_document.h"
#include "chrome/browser/chromeos/extensions/device_local_account_external_policy_loader.h"
#include "chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader.h"
#include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chromeos/chromeos_paths.h"
#include "components/arc/arc_util.h"
#else
#include "chrome/browser/extensions/default_apps.h"
......@@ -693,14 +696,18 @@ void ExternalProviderImpl::CreateExternalProviders(
// For Chrome OS demo sessions, add pre-installed demo extensions and apps.
if (chromeos::DemoExtensionsExternalLoader::SupportedForProfile(profile)) {
base::FilePath cache_dir;
CHECK(base::PathService::Get(chromeos::DIR_DEVICE_EXTENSION_LOCAL_CACHE,
&cache_dir));
scoped_refptr<chromeos::DemoExtensionsExternalLoader> loader =
base::MakeRefCounted<chromeos::DemoExtensionsExternalLoader>(cache_dir);
std::unique_ptr<ExternalProviderImpl> demo_apps_provider =
std::make_unique<ExternalProviderImpl>(
service,
base::MakeRefCounted<chromeos::DemoExtensionsExternalLoader>(),
profile, Manifest::EXTERNAL_PREF, Manifest::INVALID_LOCATION,
Extension::NO_FLAGS);
service, loader, profile, Manifest::EXTERNAL_PREF,
Manifest::EXTERNAL_PREF_DOWNLOAD, Extension::NO_FLAGS);
demo_apps_provider->set_auto_acknowledge(true);
demo_apps_provider->set_install_immediately(true);
chromeos::DemoSession::Get()->set_extensions_external_loader(loader);
provider_list->push_back(std::move(demo_apps_provider));
}
......
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