Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / chromeos / extensions / external_pref_cache_loader.cc
blob6c91f9e589898391bce616ec2f882ffc5c5ef0c3
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/extensions/external_pref_cache_loader.h"
7 #include <map>
8 #include <utility>
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/command_line.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/sequenced_task_runner.h"
15 #include "base/threading/sequenced_worker_pool.h"
16 #include "base/values.h"
17 #include "base/version.h"
18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/chromeos/extensions/external_cache.h"
20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/extensions/extension_system.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/common/extensions/extension_constants.h"
24 #include "chromeos/chromeos_switches.h"
25 #include "content/public/browser/browser_thread.h"
27 namespace chromeos {
29 namespace {
31 // Directory where the extensions are cached.
32 const char kPreinstalledAppsCacheDir[] = "/var/cache/external_cache";
34 } // namespace
36 // Ref-counted class that holds ExternalCache and dispatches cache update events
37 // to per-profile instances of ExternalPrefCacheLoader. This multiplexing
38 // is required for multi-profile case.
39 class ExternalCacheDispatcher
40 : public ExternalCache::Delegate,
41 public base::RefCounted<ExternalCacheDispatcher> {
42 public:
43 static ExternalCacheDispatcher* GetInstance() {
44 if (!ExternalCacheDispatcher::instance_)
45 ExternalCacheDispatcher::instance_ = new ExternalCacheDispatcher;
46 return instance_;
49 // Implementation of ExternalCache::Delegate:
50 virtual void OnExtensionListsUpdated(
51 const base::DictionaryValue* prefs) OVERRIDE {
52 is_extensions_list_ready_ = true;
53 for (LoadersMap::iterator it = pref_loaders_.begin();
54 it != pref_loaders_.end(); ++it) {
55 it->first->OnExtensionListsUpdated(prefs);
59 virtual std::string GetInstalledExtensionVersion(
60 const std::string& id) OVERRIDE {
61 // Return lowest installed version. Updater will download an update if
62 // CWS has higher version. Version returned here matters only if file is
63 // missing in .crx cache.
64 base::Version version;
65 for (LoadersMap::iterator it = pref_loaders_.begin();
66 it != pref_loaders_.end(); ++it) {
67 ExtensionServiceInterface* extension_service =
68 extensions::ExtensionSystem::Get(it->second)->extension_service();
69 const extensions::Extension* extension = extension_service ?
70 extension_service->GetExtensionById(id, true) : NULL;
71 if (extension) {
72 if (!version.IsValid() || extension->version()->CompareTo(version) < 0)
73 version = *extension->version();
76 return version.IsValid() ? version.GetString() : std::string();
79 void UpdateExtensionsList(scoped_ptr<base::DictionaryValue> prefs) {
80 DCHECK(!is_extensions_list_ready_);
81 external_cache_.UpdateExtensionsList(prefs.Pass());
84 // Return false if cache doesn't have list of extensions and it needs to
85 // be provided via UpdateExtensionsList.
86 bool RegisterExternalPrefCacheLoader(ExternalPrefCacheLoader* observer,
87 int base_path_id,
88 Profile* profile) {
89 pref_loaders_.insert(std::make_pair(observer, profile));
91 if (base_path_id_ == 0) {
92 // First ExternalPrefCacheLoader is registered.
93 base_path_id_ = base_path_id;
94 return false;
95 } else {
96 CHECK_EQ(base_path_id_, base_path_id);
97 if (is_extensions_list_ready_) {
98 // If list of extensions is not ready, |observer| will be notified later
99 // in OnExtensionListsUpdated.
100 observer->OnExtensionListsUpdated(external_cache_.cached_extensions());
102 return true;
106 void UnregisterExternalPrefCacheLoader(ExternalPrefCacheLoader* observer) {
107 pref_loaders_.erase(observer);
110 private:
111 friend class base::RefCounted<ExternalCacheDispatcher>;
113 typedef std::map<ExternalPrefCacheLoader*, Profile*> LoadersMap;
115 ExternalCacheDispatcher()
116 : external_cache_(base::FilePath(kPreinstalledAppsCacheDir),
117 g_browser_process->system_request_context(),
118 content::BrowserThread::GetBlockingPool()->
119 GetSequencedTaskRunnerWithShutdownBehavior(
120 content::BrowserThread::GetBlockingPool()->
121 GetSequenceToken(),
122 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN),
123 this,
124 true,
125 true),
126 base_path_id_(0),
127 is_extensions_list_ready_(false) {
128 DCHECK(!ExternalCacheDispatcher::instance_);
131 virtual ~ExternalCacheDispatcher() {
132 ExternalCacheDispatcher::instance_ = NULL;
135 ExternalCache external_cache_;
136 LoadersMap pref_loaders_;
137 int base_path_id_;
138 bool is_extensions_list_ready_;
140 static ExternalCacheDispatcher* instance_;
142 DISALLOW_COPY_AND_ASSIGN(ExternalCacheDispatcher);
145 ExternalCacheDispatcher* ExternalCacheDispatcher::instance_ = NULL;
147 ExternalPrefCacheLoader::ExternalPrefCacheLoader(int base_path_id,
148 Profile* profile)
149 : ExternalPrefLoader(base_path_id, ExternalPrefLoader::NONE),
150 profile_(profile),
151 cache_dispatcher_(ExternalCacheDispatcher::GetInstance()) {
154 ExternalPrefCacheLoader::~ExternalPrefCacheLoader() {
155 cache_dispatcher_->UnregisterExternalPrefCacheLoader(this);
158 void ExternalPrefCacheLoader::OnExtensionListsUpdated(
159 const base::DictionaryValue* prefs) {
160 prefs_.reset(prefs->DeepCopy());
161 ExternalPrefLoader::LoadFinished();
164 void ExternalPrefCacheLoader::StartLoading() {
165 if (!cache_dispatcher_->RegisterExternalPrefCacheLoader(
166 this, base_path_id_, profile_)) {
167 // ExternalCacheDispatcher doesn't know list of extensions load it.
168 ExternalPrefLoader::StartLoading();
172 void ExternalPrefCacheLoader::LoadFinished() {
173 cache_dispatcher_->UpdateExtensionsList(prefs_.Pass());
176 } // namespace chromeos