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