Commit c5319cda authored by jennyz@chromium.org's avatar jennyz@chromium.org

Download and cache kiosk app extension when it is added via kiosk mamangement ui.

BUG=369550
R=xiyuan@chromium.org

Review URL: https://codereview.chromium.org/269573010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267988 0039d316-1c4b-4281-b951-d872f2087c98
parent 90e62646
......@@ -8,6 +8,7 @@
#include <set>
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/prefs/pref_registry_simple.h"
......@@ -23,7 +24,10 @@
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/owner_key_util.h"
#include "chrome/browser/extensions/external_provider_impl.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chromeos/chromeos_paths.h"
#include "chromeos/cryptohome/async_method_caller.h"
#include "chromeos/settings/cros_settings_names.h"
#include "content/public/browser/browser_thread.h"
......@@ -54,13 +58,21 @@ void CheckOwnerFilePresence(bool *present) {
*present = util->IsPublicKeyPresent();
}
scoped_refptr<base::SequencedTaskRunner> GetBackgroundTaskRunner() {
base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
CHECK(pool);
return pool->GetSequencedTaskRunnerWithShutdownBehavior(
pool->GetSequenceToken(), base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
}
} // namespace
// static
const char KioskAppManager::kKioskDictionaryName[] = "kiosk";
const char KioskAppManager::kKeyApps[] = "apps";
const char KioskAppManager::kKeyAutoLoginState[] = "auto_login_state";
const char KioskAppManager::kIconCacheDir[] = "kiosk";
const char KioskAppManager::kIconCacheDir[] = "kiosk/icon";
const char KioskAppManager::kCrxCacheDir[] = "kiosk/crx";
// static
static base::LazyInstance<KioskAppManager> instance = LAZY_INSTANCE_INITIALIZER;
......@@ -81,12 +93,12 @@ void KioskAppManager::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterDictionaryPref(kKioskDictionaryName);
}
KioskAppManager::App::App(const KioskAppData& data)
KioskAppManager::App::App(const KioskAppData& data, bool is_extension_pending)
: app_id(data.app_id()),
user_id(data.user_id()),
name(data.name()),
icon(data.icon()),
is_loading(data.IsLoading()) {
is_loading(data.IsLoading() || is_extension_pending) {
}
KioskAppManager::App::App() : is_loading(false) {}
......@@ -292,7 +304,8 @@ void KioskAppManager::GetApps(Apps* apps) const {
for (size_t i = 0; i < apps_.size(); ++i) {
const KioskAppData& app_data = *apps_[i];
if (app_data.status() != KioskAppData::STATUS_ERROR)
apps->push_back(App(app_data));
apps->push_back(App(
app_data, external_cache_->IsExtensionPending(app_data.app_id())));
}
}
......@@ -301,7 +314,7 @@ bool KioskAppManager::GetApp(const std::string& app_id, App* app) const {
if (!data)
return false;
*app = App(*data);
*app = App(*data, external_cache_->IsExtensionPending(app_id));
return true;
}
......@@ -352,6 +365,16 @@ void KioskAppManager::RemoveObserver(KioskAppManagerObserver* observer) {
}
KioskAppManager::KioskAppManager() : ownership_established_(false) {
base::FilePath cache_dir;
GetKioskAppCrxCacheDir(&cache_dir);
external_cache_.reset(
new ExternalCache(cache_dir,
g_browser_process->system_request_context(),
GetBackgroundTaskRunner(),
this,
true /* always_check_updates */,
false /* wait_for_cache_initialization */));
UpdateAppData();
local_accounts_subscription_ =
CrosSettings::Get()->AddSettingsObserver(
......@@ -369,6 +392,7 @@ void KioskAppManager::CleanUp() {
local_accounts_subscription_.reset();
local_account_auto_login_id_subscription_.reset();
apps_.clear();
external_cache_.reset();
}
const KioskAppData* KioskAppManager::GetAppData(
......@@ -426,14 +450,24 @@ void KioskAppManager::UpdateAppData() {
}
// Clears cache and deletes the remaining old data.
std::vector<std::string> apps_to_remove;
for (std::map<std::string, KioskAppData*>::iterator it = old_apps.begin();
it != old_apps.end(); ++it) {
it->second->ClearCache();
cryptohome::AsyncMethodCaller::GetInstance()->AsyncRemove(
it->second->user_id(),
base::Bind(&OnRemoveAppCryptohomeComplete, it->first));
apps_to_remove.push_back(it->second->app_id());
}
STLDeleteValues(&old_apps);
external_cache_->RemoveExtensions(apps_to_remove);
// Request external_cache_ to download new apps and update the existing
// apps.
scoped_ptr<base::DictionaryValue> prefs(new base::DictionaryValue);
for (size_t i = 0; i < apps_.size(); ++i)
prefs->Set(apps_[i]->app_id(), new base::DictionaryValue);
external_cache_->UpdateExtensionsList(prefs.Pass());
FOR_EACH_OBSERVER(KioskAppManagerObserver, observers_,
OnKioskAppsSettingsChanged());
......@@ -457,6 +491,26 @@ void KioskAppManager::OnKioskAppDataLoadFailure(const std::string& app_id) {
OnKioskAppDataLoadFailure(app_id));
}
void KioskAppManager::OnExtensionListsUpdated(
const base::DictionaryValue* prefs) {
}
void KioskAppManager::OnExtensionLoadedInCache(const std::string& id) {
KioskAppData* app_data = GetAppDataMutable(id);
if (!app_data)
return;
OnKioskAppDataChanged(id);
}
void KioskAppManager::OnExtensionDownloadFailed(
const std::string& id,
extensions::ExtensionDownloaderDelegate::Error error) {
KioskAppData* app_data = GetAppDataMutable(id);
if (!app_data)
return;
OnKioskAppDataLoadFailure(id);
}
KioskAppManager::AutoLoginState KioskAppManager::GetAutoLoginState() const {
PrefService* prefs = g_browser_process->local_state();
const base::DictionaryValue* dict =
......@@ -476,4 +530,10 @@ void KioskAppManager::SetAutoLoginState(AutoLoginState state) {
prefs->CommitPendingWrite();
}
void KioskAppManager::GetKioskAppCrxCacheDir(base::FilePath* cache_dir) {
base::FilePath user_data_dir;
CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
*cache_dir = user_data_dir.AppendASCII(kCrxCacheDir);
}
} // namespace chromeos
......@@ -15,6 +15,7 @@
#include "base/memory/scoped_vector.h"
#include "base/observer_list.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_data_delegate.h"
#include "chrome/browser/chromeos/extensions/external_cache.h"
#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "ui/gfx/image/image_skia.h"
......@@ -36,7 +37,8 @@ class KioskAppData;
class KioskAppManagerObserver;
// KioskAppManager manages cached app data.
class KioskAppManager : public KioskAppDataDelegate {
class KioskAppManager : public KioskAppDataDelegate,
public ExternalCache::Delegate {
public:
enum ConsumerKioskAutoLaunchStatus {
// Consumer kiosk mode auto-launch feature can be enabled on this machine.
......@@ -54,7 +56,7 @@ class KioskAppManager : public KioskAppDataDelegate {
// Struct to hold app info returned from GetApps() call.
struct App {
explicit App(const KioskAppData& data);
App(const KioskAppData& data, bool is_extension_pending);
App();
~App();
......@@ -78,6 +80,9 @@ class KioskAppManager : public KioskAppDataDelegate {
// Sub directory under DIR_USER_DATA to store cached icon files.
static const char kIconCacheDir[];
// Sub directory under DIR_USER_DATA to store cached crx files.
static const char kCrxCacheDir[];
// Gets the KioskAppManager instance, which is lazily created on first call..
static KioskAppManager* Get();
......@@ -179,6 +184,14 @@ class KioskAppManager : public KioskAppDataDelegate {
virtual void OnKioskAppDataChanged(const std::string& app_id) OVERRIDE;
virtual void OnKioskAppDataLoadFailure(const std::string& app_id) OVERRIDE;
// ExternalCache::Delegate:
virtual void OnExtensionListsUpdated(
const base::DictionaryValue* prefs) OVERRIDE;
virtual void OnExtensionLoadedInCache(const std::string& id) OVERRIDE;
virtual void OnExtensionDownloadFailed(
const std::string& id,
extensions::ExtensionDownloaderDelegate::Error error) OVERRIDE;
// Callback for EnterpriseInstallAttributes::LockDevice() during
// EnableConsumerModeKiosk() call.
void OnLockDevice(
......@@ -199,6 +212,8 @@ class KioskAppManager : public KioskAppDataDelegate {
AutoLoginState GetAutoLoginState() const;
void SetAutoLoginState(AutoLoginState state);
void GetKioskAppCrxCacheDir(base::FilePath* cache_dir);
// True if machine ownership is already established.
bool ownership_established_;
ScopedVector<KioskAppData> apps_;
......@@ -210,6 +225,8 @@ class KioskAppManager : public KioskAppDataDelegate {
scoped_ptr<CrosSettings::ObserverSubscription>
local_account_auto_login_id_subscription_;
scoped_ptr<ExternalCache> external_cache_;
DISALLOW_COPY_AND_ASSIGN(KioskAppManager);
};
......
......@@ -108,6 +108,18 @@ void ExternalCache::OnDamagedFileDetected(const base::FilePath& path) {
LOG(ERROR) << "ExternalCache cannot find external_crx " << path.value();
}
void ExternalCache::RemoveExtensions(const std::vector<std::string>& ids) {
if (ids.empty())
return;
for (size_t i = 0; i < ids.size(); ++i) {
cached_extensions_->Remove(ids[i], NULL);
extensions_->Remove(ids[i], NULL);
local_cache_.RemoveExtension(ids[i]);
}
UpdateExtensionLoader();
}
void ExternalCache::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
......@@ -133,10 +145,14 @@ void ExternalCache::OnExtensionDownloadFailed(
if (!cached_extensions_->HasKey(id)) {
LOG(ERROR) << "ExternalCache extension " << id
<< " not found on update server";
delegate_->OnExtensionDownloadFailed(id, error);
} else {
delegate_->OnExtensionLoadedInCache(id);
}
} else {
LOG(ERROR) << "ExternalCache failed to download extension " << id
<< ", error " << error;
delegate_->OnExtensionDownloadFailed(id, error);
}
}
......@@ -293,6 +309,8 @@ void ExternalCache::OnPutExtension(const std::string& id,
file_path.value());
cached_extensions_->Set(id, entry);
if (delegate_)
delegate_->OnExtensionLoadedInCache(id);
UpdateExtensionLoader();
}
......
......@@ -44,6 +44,12 @@ class ExternalCache : public content::NotificationObserver,
// Caller owns |prefs|.
virtual void OnExtensionListsUpdated(
const base::DictionaryValue* prefs) = 0;
// Called after extension with |id| is loaded in cache.
virtual void OnExtensionLoadedInCache(const std::string& id) {}
// Called when extension with |id| is failed with downloading for |error|.
virtual void OnExtensionDownloadFailed(
const std::string& id,
extensions::ExtensionDownloaderDelegate::Error error) {}
// Cache needs to provide already installed extensions otherwise they
// will be removed. Cache calls this function to get version of installed
......@@ -110,6 +116,10 @@ class ExternalCache : public content::NotificationObserver,
// the cache and retry to download it after a restart.
void OnDamagedFileDetected(const base::FilePath& path);
// Removes extensions listed in |ids| from external cache, corresponding crx
// files will be removed from disk too.
void RemoveExtensions(const std::vector<std::string>& ids);
private:
// Notifies the that the cache has been updated, providing
// extensions loader with an updated list of extensions.
......
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