Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3694)

Unified Diff: chrome/browser/policy/app_pack_updater.cc

Issue 12189011: Split up chrome/browser/policy subdirectory (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase, add chrome/browser/chromeos/policy/OWNERS Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/policy/app_pack_updater.h ('k') | chrome/browser/policy/auto_enrollment_client.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/policy/app_pack_updater.cc
diff --git a/chrome/browser/policy/app_pack_updater.cc b/chrome/browser/policy/app_pack_updater.cc
deleted file mode 100644
index 2a0b9de88214bf515726be2f0472b1c505eb46ac..0000000000000000000000000000000000000000
--- a/chrome/browser/policy/app_pack_updater.cc
+++ /dev/null
@@ -1,572 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/policy/app_pack_updater.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/file_util.h"
-#include "base/location.h"
-#include "base/stl_util.h"
-#include "base/string_util.h"
-#include "base/values.h"
-#include "base/version.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/settings/cros_settings.h"
-#include "chrome/browser/chromeos/settings/cros_settings_names.h"
-#include "chrome/browser/extensions/crx_installer.h"
-#include "chrome/browser/extensions/external_loader.h"
-#include "chrome/browser/extensions/external_provider_impl.h"
-#include "chrome/browser/extensions/updater/extension_downloader.h"
-#include "chrome/browser/policy/enterprise_install_attributes.h"
-#include "chrome/common/chrome_notification_types.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_constants.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
-
-using content::BrowserThread;
-using file_util::FileEnumerator;
-
-namespace policy {
-
-namespace {
-
-// Directory where the AppPack extensions are cached.
-const char kAppPackCacheDir[] = "/var/cache/app_pack";
-
-// File name extension for CRX files (not case sensitive).
-const char kCRXFileExtension[] = ".crx";
-
-} // namespace
-
-const char AppPackUpdater::kExtensionId[] = "extension-id";
-const char AppPackUpdater::kUpdateUrl[] = "update-url";
-
-// A custom extensions::ExternalLoader that the AppPackUpdater creates and uses
-// to publish AppPack updates to the extensions system.
-class AppPackExternalLoader
- : public extensions::ExternalLoader,
- public base::SupportsWeakPtr<AppPackExternalLoader> {
- public:
- AppPackExternalLoader() {}
-
- // Used by the AppPackUpdater to update the current list of extensions.
- // The format of |prefs| is detailed in the extensions::ExternalLoader/
- // Provider headers.
- void SetCurrentAppPackExtensions(scoped_ptr<base::DictionaryValue> prefs) {
- app_pack_prefs_.Swap(prefs.get());
- StartLoading();
- }
-
- // Implementation of extensions::ExternalLoader:
- virtual void StartLoading() OVERRIDE {
- prefs_.reset(app_pack_prefs_.DeepCopy());
- VLOG(1) << "AppPack extension loader publishing "
- << app_pack_prefs_.size() << " crx files.";
- LoadFinished();
- }
-
- protected:
- virtual ~AppPackExternalLoader() {}
-
- private:
- base::DictionaryValue app_pack_prefs_;
-
- DISALLOW_COPY_AND_ASSIGN(AppPackExternalLoader);
-};
-
-AppPackUpdater::AppPackUpdater(net::URLRequestContextGetter* request_context,
- EnterpriseInstallAttributes* install_attributes)
- : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
- initialized_(false),
- created_extension_loader_(false),
- request_context_(request_context),
- install_attributes_(install_attributes) {
- chromeos::CrosSettings::Get()->AddSettingsObserver(chromeos::kAppPack, this);
-
- if (install_attributes_->GetMode() == DEVICE_MODE_KIOSK) {
- // Already in Kiosk mode, start loading.
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&AppPackUpdater::Init,
- weak_ptr_factory_.GetWeakPtr()));
- } else {
- // Linger until the device switches to DEVICE_MODE_KIOSK and the app pack
- // device setting appears.
- }
-}
-
-AppPackUpdater::~AppPackUpdater() {
- chromeos::CrosSettings::Get()->RemoveSettingsObserver(
- chromeos::kAppPack, this);
-}
-
-extensions::ExternalLoader* AppPackUpdater::CreateExternalLoader() {
- if (created_extension_loader_) {
- NOTREACHED();
- return NULL;
- }
- created_extension_loader_ = true;
- AppPackExternalLoader* loader = new AppPackExternalLoader();
- extension_loader_ = loader->AsWeakPtr();
-
- // The cache may have been already checked. In that case, load the current
- // extensions into the loader immediately.
- UpdateExtensionLoader();
-
- return loader;
-}
-
-void AppPackUpdater::SetScreenSaverUpdateCallback(
- const AppPackUpdater::ScreenSaverUpdateCallback& callback) {
- screen_saver_update_callback_ = callback;
- if (!screen_saver_update_callback_.is_null() && !screen_saver_path_.empty()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(screen_saver_update_callback_, screen_saver_path_));
- }
-}
-
-void AppPackUpdater::Init() {
- if (initialized_)
- return;
-
- initialized_ = true;
- worker_pool_token_ = BrowserThread::GetBlockingPool()->GetSequenceToken();
- notification_registrar_.Add(
- this,
- chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
- content::NotificationService::AllBrowserContextsAndSources());
- LoadPolicy();
-}
-
-void AppPackUpdater::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- switch (type) {
- case chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED:
- DCHECK_EQ(chromeos::kAppPack,
- *content::Details<const std::string>(details).ptr());
- if (install_attributes_->GetMode() == DEVICE_MODE_KIOSK) {
- if (!initialized_)
- Init();
- else
- LoadPolicy();
- }
- break;
-
- case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: {
- extensions::CrxInstaller* installer =
- content::Source<extensions::CrxInstaller>(source).ptr();
- OnDamagedFileDetected(installer->source_file());
- break;
- }
-
- default:
- NOTREACHED();
- }
-}
-
-void AppPackUpdater::LoadPolicy() {
- chromeos::CrosSettings* settings = chromeos::CrosSettings::Get();
- if (chromeos::CrosSettingsProvider::TRUSTED != settings->PrepareTrustedValues(
- base::Bind(&AppPackUpdater::LoadPolicy,
- weak_ptr_factory_.GetWeakPtr()))) {
- return;
- }
-
- app_pack_extensions_.clear();
- const base::Value* value = settings->GetPref(chromeos::kAppPack);
- const base::ListValue* list = NULL;
- if (value && value->GetAsList(&list)) {
- for (base::ListValue::const_iterator it = list->begin();
- it != list->end(); ++it) {
- base::DictionaryValue* dict = NULL;
- if (!(*it)->GetAsDictionary(&dict)) {
- LOG(WARNING) << "AppPack entry is not a dictionary, ignoring.";
- continue;
- }
- std::string id;
- std::string update_url;
- if (dict->GetString(kExtensionId, &id) &&
- dict->GetString(kUpdateUrl, &update_url)) {
- app_pack_extensions_[id] = update_url;
- } else {
- LOG(WARNING) << "Failed to read required fields for an AppPack entry, "
- << "ignoring.";
- }
- }
- }
-
- VLOG(1) << "Refreshed AppPack policy, got " << app_pack_extensions_.size()
- << " entries.";
-
- value = settings->GetPref(chromeos::kScreenSaverExtensionId);
- if (!value || !value->GetAsString(&screen_saver_id_)) {
- screen_saver_id_.clear();
- SetScreenSaverPath(base::FilePath());
- }
-
- CheckCacheNow();
-}
-
-void AppPackUpdater::CheckCacheNow() {
- std::set<std::string>* valid_ids = new std::set<std::string>();
- for (PolicyEntryMap::iterator it = app_pack_extensions_.begin();
- it != app_pack_extensions_.end(); ++it) {
- valid_ids->insert(it->first);
- }
- PostBlockingTask(FROM_HERE,
- base::Bind(&AppPackUpdater::BlockingCheckCache,
- weak_ptr_factory_.GetWeakPtr(),
- base::Owned(valid_ids)));
-}
-
-// static
-void AppPackUpdater::BlockingCheckCache(
- base::WeakPtr<AppPackUpdater> app_pack_updater,
- const std::set<std::string>* valid_ids) {
- CacheEntryMap* entries = new CacheEntryMap();
- BlockingCheckCacheInternal(valid_ids, entries);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&AppPackUpdater::OnCacheUpdated,
- app_pack_updater,
- base::Owned(entries)));
-}
-
-// static
-void AppPackUpdater::BlockingCheckCacheInternal(
- const std::set<std::string>* valid_ids,
- CacheEntryMap* entries) {
- // Start by verifying that the cache dir exists.
- base::FilePath dir(kAppPackCacheDir);
- if (!file_util::DirectoryExists(dir)) {
- // Create it now.
- if (!file_util::CreateDirectory(dir))
- LOG(ERROR) << "Failed to create AppPack directory at " << dir.value();
- // Nothing else to do.
- return;
- }
-
- // Enumerate all the files in the cache |dir|, including directories
- // and symlinks. Each unrecognized file will be erased.
- int types = FileEnumerator::FILES | FileEnumerator::DIRECTORIES |
- FileEnumerator::SHOW_SYM_LINKS;
- FileEnumerator enumerator(dir, false /* recursive */, types);
-
- for (base::FilePath path = enumerator.Next();
- !path.empty(); path = enumerator.Next()) {
- FileEnumerator::FindInfo info;
- enumerator.GetFindInfo(&info);
- std::string basename = path.BaseName().value();
-
- if (FileEnumerator::IsDirectory(info) ||
- file_util::IsLink(FileEnumerator::GetFilename(info))) {
- LOG(ERROR) << "Erasing bad file in AppPack directory: " << basename;
- file_util::Delete(path, true /* recursive */);
- continue;
- }
-
- // crx files in the cache are named <extension-id>-<version>.crx.
- std::string id;
- std::string version;
-
- if (EndsWith(basename, kCRXFileExtension, false /* case-sensitive */)) {
- size_t n = basename.find('-');
- if (n != std::string::npos && n + 1 < basename.size() - 4) {
- id = basename.substr(0, n);
- // Size of |version| = total size - "<id>" - "-" - ".crx"
- version = basename.substr(n + 1, basename.size() - 5 - id.size());
- }
- }
-
- if (!extensions::Extension::IdIsValid(id)) {
- LOG(ERROR) << "Bad AppPack extension id in cache: " << id;
- id.clear();
- } else if (!ContainsKey(*valid_ids, id)) {
- LOG(WARNING) << basename << " is in the cache but is not configured by "
- << "the AppPack policy, and will be erased.";
- id.clear();
- }
-
- if (!Version(version).IsValid()) {
- LOG(ERROR) << "Bad AppPack extension version in cache: " << version;
- version.clear();
- }
-
- if (id.empty() || version.empty()) {
- LOG(ERROR) << "Invalid file in AppPack cache, erasing: " << basename;
- file_util::Delete(path, true /* recursive */);
- continue;
- }
-
- // Enforce a lower-case id.
- id = StringToLowerASCII(id);
-
- // File seems good so far. Make sure there isn't another entry with the
- // same id but a different version.
-
- if (ContainsKey(*entries, id)) {
- LOG(ERROR) << "Found two AppPack files for the same extension, will "
- "erase the oldest version";
- CacheEntry& entry = (*entries)[id];
- Version vEntry(entry.cached_version);
- Version vCurrent(version);
- DCHECK(vEntry.IsValid());
- DCHECK(vCurrent.IsValid());
- if (vEntry.CompareTo(vCurrent) < 0) {
- file_util::Delete(base::FilePath(entry.path), true /* recursive */);
- entry.path = path.value();
- } else {
- file_util::Delete(path, true /* recursive */);
- }
- continue;
- }
-
- // This is the only file for this |id| so far, add it.
-
- CacheEntry& entry = (*entries)[id];
- entry.path = path.value();
- entry.cached_version = version;
- }
-}
-
-void AppPackUpdater::OnCacheUpdated(CacheEntryMap* cache_entries) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- cached_extensions_.swap(*cache_entries);
-
- CacheEntryMap::iterator it = cached_extensions_.find(screen_saver_id_);
- if (it != cached_extensions_.end())
- SetScreenSaverPath(base::FilePath(it->second.path));
- else
- SetScreenSaverPath(base::FilePath());
-
- VLOG(1) << "Updated AppPack cache, there are " << cached_extensions_.size()
- << " extensions cached and "
- << (screen_saver_path_.empty() ? "no" : "the") << " screensaver";
- UpdateExtensionLoader();
- DownloadMissingExtensions();
-}
-
-void AppPackUpdater::UpdateExtensionLoader() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (!extension_loader_) {
- VLOG(1) << "No AppPack loader created yet, not pushing extensions.";
- return;
- }
-
- // Build a DictionaryValue with the format that
- // extensions::ExternalProviderImpl expects, containing info about the locally
- // cached extensions.
-
- scoped_ptr<base::DictionaryValue> prefs(new base::DictionaryValue());
- for (CacheEntryMap::iterator it = cached_extensions_.begin();
- it != cached_extensions_.end(); ++it) {
- const std::string& id = it->first;
- // The screensaver isn't installed into the Profile.
- if (id == screen_saver_id_)
- continue;
-
- base::DictionaryValue* dict = new base::DictionaryValue();
- dict->SetString(extensions::ExternalProviderImpl::kExternalCrx,
- it->second.path);
- dict->SetString(extensions::ExternalProviderImpl::kExternalVersion,
- it->second.cached_version);
-
- // Include this optional flag if the extension's update url is the Webstore.
- PolicyEntryMap::iterator policy_entry = app_pack_extensions_.find(id);
- if (policy_entry != app_pack_extensions_.end() &&
- extension_urls::IsWebstoreUpdateUrl(
- GURL(policy_entry->second))) {
- dict->SetBoolean(extensions::ExternalProviderImpl::kIsFromWebstore, true);
- }
-
- prefs->Set(it->first, dict);
-
- VLOG(1) << "Updating AppPack extension loader, added " << it->second.path;
- }
-
- extension_loader_->SetCurrentAppPackExtensions(prefs.Pass());
-}
-
-void AppPackUpdater::DownloadMissingExtensions() {
- // Check for updates for all extensions configured by the policy. Some of
- // them may already be in the cache; only those with updated version will be
- // downloaded, in that case.
- if (!downloader_.get()) {
- downloader_.reset(new extensions::ExtensionDownloader(this,
- request_context_));
- }
- for (PolicyEntryMap::iterator it = app_pack_extensions_.begin();
- it != app_pack_extensions_.end(); ++it) {
- downloader_->AddPendingExtension(it->first, GURL(it->second), 0);
- }
- VLOG(1) << "Downloading AppPack update manifest now";
- downloader_->StartAllPending();
-}
-
-void AppPackUpdater::OnExtensionDownloadFailed(
- const std::string& id,
- extensions::ExtensionDownloaderDelegate::Error error,
- const extensions::ExtensionDownloaderDelegate::PingResult& ping_result,
- const std::set<int>& request_ids) {
- if (error == NO_UPDATE_AVAILABLE) {
- if (!ContainsKey(cached_extensions_, id))
- LOG(ERROR) << "AppPack extension " << id << " not found on update server";
- } else {
- LOG(ERROR) << "AppPack failed to download extension " << id
- << ", error " << error;
- }
-}
-
-void AppPackUpdater::OnExtensionDownloadFinished(
- const std::string& id,
- const base::FilePath& path,
- const GURL& download_url,
- const std::string& version,
- const extensions::ExtensionDownloaderDelegate::PingResult& ping_result,
- const std::set<int>& request_ids) {
- // The explicit copy ctors are to make sure that Bind() binds a copy and not
- // a reference to the arguments.
- PostBlockingTask(FROM_HERE,
- base::Bind(&AppPackUpdater::BlockingInstallCacheEntry,
- weak_ptr_factory_.GetWeakPtr(),
- std::string(id),
- base::FilePath(path),
- std::string(version)));
-}
-
-void AppPackUpdater::OnBlacklistDownloadFinished(
- const std::string& data,
- const std::string& package_hash,
- const std::string& version,
- const extensions::ExtensionDownloaderDelegate::PingResult& ping_result,
- const std::set<int>& request_ids) {
- NOTREACHED();
-}
-
-bool AppPackUpdater::IsExtensionPending(const std::string& id) {
- // Pending means that there is no installed version yet.
- return ContainsKey(app_pack_extensions_, id) &&
- !ContainsKey(cached_extensions_, id);
-}
-
-bool AppPackUpdater::GetExtensionExistingVersion(const std::string& id,
- std::string* version) {
- if (!ContainsKey(app_pack_extensions_, id) ||
- !ContainsKey(cached_extensions_, id)) {
- return false;
- }
-
- *version = cached_extensions_[id].cached_version;
- return true;
-}
-
-// static
-void AppPackUpdater::BlockingInstallCacheEntry(
- base::WeakPtr<AppPackUpdater> app_pack_updater,
- const std::string& id,
- const base::FilePath& path,
- const std::string& version) {
- Version version_validator(version);
- if (!version_validator.IsValid()) {
- LOG(ERROR) << "AppPack downloaded extension " << id << " but got bad "
- << "version: " << version;
- file_util::Delete(path, true /* recursive */);
- return;
- }
-
- std::string basename = id + "-" + version + kCRXFileExtension;
- base::FilePath cache_dir(kAppPackCacheDir);
- base::FilePath cached_crx_path = cache_dir.Append(basename);
-
- if (file_util::PathExists(cached_crx_path)) {
- LOG(WARNING) << "AppPack downloaded a crx whose filename will overwrite "
- << "an existing cached crx.";
- file_util::Delete(cached_crx_path, true /* recursive */);
- }
-
- if (!file_util::DirectoryExists(cache_dir)) {
- LOG(ERROR) << "AppPack cache directory does not exist, creating now: "
- << cache_dir.value();
- if (!file_util::CreateDirectory(cache_dir)) {
- LOG(ERROR) << "Failed to create the AppPack cache dir!";
- file_util::Delete(path, true /* recursive */);
- return;
- }
- }
-
- if (!file_util::Move(path, cached_crx_path)) {
- LOG(ERROR) << "Failed to move AppPack crx from " << path.value()
- << " to " << cached_crx_path.value();
- file_util::Delete(path, true /* recursive */);
- return;
- }
-
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&AppPackUpdater::OnCacheEntryInstalled,
- app_pack_updater,
- std::string(id),
- cached_crx_path.value(),
- std::string(version)));
-}
-
-void AppPackUpdater::OnCacheEntryInstalled(const std::string& id,
- const std::string& path,
- const std::string& version) {
- VLOG(1) << "AppPack installed a new extension in the cache: " << path;
- // Add to the list of cached extensions.
- CacheEntry& entry = cached_extensions_[id];
- entry.path = path;
- entry.cached_version = version;
-
- if (id == screen_saver_id_) {
- VLOG(1) << "AppPack got the screen saver extension at " << path;
- SetScreenSaverPath(base::FilePath(path));
- } else {
- UpdateExtensionLoader();
- }
-}
-
-void AppPackUpdater::OnDamagedFileDetected(const base::FilePath& path) {
- // Search for |path| in |cached_extensions_|, and delete it if found.
- for (CacheEntryMap::iterator it = cached_extensions_.begin();
- it != cached_extensions_.end(); ++it) {
- if (it->second.path == path.value()) {
- LOG(ERROR) << "AppPack extension at " << path.value() << " failed to "
- << "install, deleting it.";
- cached_extensions_.erase(it);
- UpdateExtensionLoader();
-
- // The file will be downloaded again on the next restart.
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(base::IgnoreResult(file_util::Delete), path, true));
-
- // Don't try to DownloadMissingExtensions() from here,
- // since it can cause a fail/retry loop.
- break;
- }
- }
-}
-
-void AppPackUpdater::PostBlockingTask(const tracked_objects::Location& location,
- const base::Closure& task) {
- BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
- worker_pool_token_, location, task,
- base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
-}
-
-void AppPackUpdater::SetScreenSaverPath(const base::FilePath& path) {
- // Don't invoke the callback if the path isn't changing.
- if (path != screen_saver_path_) {
- screen_saver_path_ = path;
- if (!screen_saver_update_callback_.is_null())
- screen_saver_update_callback_.Run(screen_saver_path_);
- }
-}
-
-} // namespace policy
« no previous file with comments | « chrome/browser/policy/app_pack_updater.h ('k') | chrome/browser/policy/auto_enrollment_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698