blob: 142ec9aee05a3a4c0bce7636bf7e64a3a3312672 [file] [log] [blame]
// 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.
#ifndef CHROME_BROWSER_POLICY_APP_PACK_UPDATER_H_
#define CHROME_BROWSER_POLICY_APP_PACK_UPDATER_H_
#include <map>
#include <set>
#include <string>
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/extensions/updater/extension_downloader_delegate.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
class GURL;
namespace extensions {
class CrxInstaller;
class ExtensionDownloader;
class ExternalLoader;
}
namespace net {
class URLRequestContextGetter;
}
namespace tracked_objects {
class Location;
}
namespace policy {
class AppPackExternalLoader;
class EnterpriseInstallAttributes;
// The AppPackUpdater manages a set of extensions that are configured via a
// device policy to be locally cached and installed into the Demo user account
// at login time.
class AppPackUpdater : public content::NotificationObserver,
public extensions::ExtensionDownloaderDelegate {
public:
// Callback to listen for updates to the screensaver extension's path.
typedef base::Callback<void(const FilePath&)> ScreenSaverUpdateCallback;
// Keys for the entries in the AppPack dictionary policy.
static const char kExtensionId[];
static const char kUpdateUrl[];
// The |request_context| is used for the update checks.
AppPackUpdater(net::URLRequestContextGetter* request_context,
EnterpriseInstallAttributes* install_attributes);
virtual ~AppPackUpdater();
// Creates an extensions::ExternalLoader that will load the crx files
// downloaded by the AppPackUpdater. This can be called at most once, and the
// caller owns the returned value.
extensions::ExternalLoader* CreateExternalLoader();
// |callback| will be invoked whenever the screen saver extension's path
// changes. It will be invoked "soon" after this call if a valid path already
// exists. Subsequent calls will override the previous |callback|. A null
// |callback| can be used to remove a previous callback.
void SetScreenSaverUpdateCallback(const ScreenSaverUpdateCallback& callback);
// If a user of one of the AppPack's extensions detects that the extension
// is damaged then this method can be used to remove it from the cache and
// retry to download it after a restart.
void OnDamagedFileDetected(const FilePath& path);
private:
struct CacheEntry {
std::string path;
std::string cached_version;
};
// Maps an extension ID to its update URL.
typedef std::map<std::string, std::string> PolicyEntryMap;
// Maps an extension ID to a CacheEntry.
typedef std::map<std::string, CacheEntry> CacheEntryMap;
void Init();
// content::NotificationObserver:
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
// Loads the current policy and schedules a cache update.
void LoadPolicy();
// Starts a cache update check immediately.
void CheckCacheNow();
// Performs a cache update check on the blocking pool. |app_pack_updater| is
// used to reply in the UI thread. |valid_ids| contains the list of IDs that
// are currently configured by policy; anything else is invalid, and should
// be removed from the cache. |valid_ids| is owned by the posted task.
static void BlockingCheckCache(base::WeakPtr<AppPackUpdater> app_pack_updater,
const std::set<std::string>* valid_ids);
// Helper for BlockingCheckCache().
static void BlockingCheckCacheInternal(
const std::set<std::string>* valid_ids,
CacheEntryMap* entries);
// Invoked when the cache has been updated. |cache_entries| contains all the
// currently valid crx files in the cache, and is owned by the posted task.
void OnCacheUpdated(CacheEntryMap* cache_entries);
// Notifies the |extension_loader_| that the cache has been updated, providing
// it with an updated list of app-pack extensions.
void UpdateExtensionLoader();
// Schedules downloads of all the extensions that are currently configured
// by the policy but missing in the cache.
void DownloadMissingExtensions();
// Implementation of ExtensionDownloaderDelegate:
virtual void OnExtensionDownloadFailed(
const std::string& id,
Error error,
const PingResult& ping_result,
const std::set<int>& request_ids) OVERRIDE;
virtual void OnExtensionDownloadFinished(
const std::string& id,
const FilePath& path,
const GURL& download_url,
const std::string& version,
const PingResult& ping_result,
const std::set<int>& request_ids) OVERRIDE;
virtual void OnBlacklistDownloadFinished(
const std::string& data,
const std::string& package_hash,
const std::string& version,
const PingResult& ping_result,
const std::set<int>& request_ids) OVERRIDE;
virtual bool IsExtensionPending(const std::string& id) OVERRIDE;
virtual bool GetExtensionExistingVersion(const std::string& id,
std::string* version) OVERRIDE;
// Invoked to install the downloaded crx file at |path| in the AppPack cache.
static void BlockingInstallCacheEntry(
base::WeakPtr<AppPackUpdater> app_pack_updater,
const std::string& id,
const FilePath& path,
const std::string& version);
// Invoked on the UI thread when a new AppPack entry has been installed in
// the AppPack cache.
void OnCacheEntryInstalled(const std::string& id,
const std::string& path,
const std::string& version);
// Handles failure to install CRX files. The file is deleted if it came from
// the cache.
void OnCrxInstallFailed(extensions::CrxInstaller* installer);
// Helper to post blocking IO tasks to the blocking pool.
void PostBlockingTask(const tracked_objects::Location& from_here,
const base::Closure& task);
// Sets |screen_saver_path_| and invokes |screen_saver_update_callback_| if
// appropriate.
void SetScreenSaverPath(const FilePath& path);
base::WeakPtrFactory<AppPackUpdater> weak_ptr_factory_;
// Observes failures to install CRX files.
content::NotificationRegistrar notification_registrar_;
// Unique sequence token so that tasks posted by the AppPackUpdater are
// executed sequentially in the blocking pool.
base::SequencedWorkerPool::SequenceToken worker_pool_token_;
// Whether the updater has initialized. This is only done if the device is in
// kiosk mode and the app pack policy is present.
bool initialized_;
// This is the list of extensions currently configured by the policy.
PolicyEntryMap app_pack_extensions_;
// This contains extensions that are both currently configured by the policy
// and that have a valid crx in the cache.
CacheEntryMap cached_extensions_;
// The extension ID and path of the CRX file of the screen saver extension,
// if it is configured by the policy. Otherwise these fields are empty.
std::string screen_saver_id_;
FilePath screen_saver_path_;
// Callback to invoke whenever the screen saver's extension path changes.
// Can be null.
ScreenSaverUpdateCallback screen_saver_update_callback_;
// The extension loader wires the AppPackUpdater to the extensions system, and
// makes it install the currently cached extensions.
bool created_extension_loader_;
base::WeakPtr<AppPackExternalLoader> extension_loader_;
// Used to download the extensions configured via policy, and to check for
// updates.
scoped_ptr<extensions::ExtensionDownloader> downloader_;
// Request context used by the |downloader_|.
net::URLRequestContextGetter* request_context_;
// For checking the device mode.
EnterpriseInstallAttributes* install_attributes_;
DISALLOW_COPY_AND_ASSIGN(AppPackUpdater);
};
} // namespace policy
#endif // CHROME_BROWSER_POLICY_APP_PACK_UPDATER_H_