1 // Copyright 2014 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/extensions/updater/extension_cache_impl.h"
8 #include "base/memory/singleton.h"
9 #include "base/metrics/histogram.h"
10 #include "base/sequenced_task_runner.h"
11 #include "base/stl_util.h"
12 #include "base/threading/sequenced_worker_pool.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/extensions/crx_installer.h"
15 #include "chrome/browser/extensions/updater/local_extension_cache.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/notification_details.h"
18 #include "content/public/browser/notification_service.h"
19 #include "content/public/browser/notification_source.h"
21 namespace extensions
{
25 const char kLocalCacheDir
[] = "/var/cache/external_cache";
27 #error Please define kLocalCacheDir suitable for target OS
28 #endif// Directory where the extensions are cached.
30 // Maximum size of local cache on disk.
31 size_t kMaxCacheSize
= 100 * 1024 * 1024;
33 // Maximum age of unused extensions in cache.
34 const int kMaxCacheAgeDays
= 30;
39 ExtensionCacheImpl
* ExtensionCacheImpl::GetInstance() {
40 return Singleton
<ExtensionCacheImpl
>::get();
43 ExtensionCacheImpl::ExtensionCacheImpl()
44 : weak_ptr_factory_(this),
45 cache_(new LocalExtensionCache(base::FilePath(kLocalCacheDir
),
47 base::TimeDelta::FromDays(kMaxCacheAgeDays
),
48 content::BrowserThread::GetBlockingPool()->
49 GetSequencedTaskRunnerWithShutdownBehavior(
50 content::BrowserThread::GetBlockingPool()->GetSequenceToken(),
51 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
))) {
52 notification_registrar_
.Add(
54 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR
,
55 content::NotificationService::AllBrowserContextsAndSources());
56 cache_
->Init(true, base::Bind(&ExtensionCacheImpl::OnCacheInitialized
,
57 weak_ptr_factory_
.GetWeakPtr()));
60 ExtensionCacheImpl::~ExtensionCacheImpl() {
63 void ExtensionCacheImpl::Start(const base::Closure
& callback
) {
64 if (!cache_
|| cache_
->is_ready()) {
65 DCHECK(init_callbacks_
.empty());
68 init_callbacks_
.push_back(callback
);
72 void ExtensionCacheImpl::Shutdown(const base::Closure
& callback
) {
74 cache_
->Shutdown(callback
);
79 void ExtensionCacheImpl::AllowCaching(const std::string
& id
) {
80 allowed_extensions_
.insert(id
);
83 bool ExtensionCacheImpl::GetExtension(const std::string
& id
,
84 base::FilePath
* file_path
,
85 std::string
* version
) {
87 return cache_
->GetExtension(id
, file_path
, version
);
92 void ExtensionCacheImpl::PutExtension(const std::string
& id
,
93 const base::FilePath
& file_path
,
94 const std::string
& version
,
95 const PutExtensionCallback
& callback
) {
96 if (cache_
&& ContainsKey(allowed_extensions_
, id
))
97 cache_
->PutExtension(id
, file_path
, version
, callback
);
99 callback
.Run(file_path
, true);
102 void ExtensionCacheImpl::OnCacheInitialized() {
103 for (std::vector
<base::Closure
>::iterator it
= init_callbacks_
.begin();
104 it
!= init_callbacks_
.end(); ++it
) {
107 init_callbacks_
.clear();
109 uint64 cache_size
= 0;
110 size_t extensions_count
= 0;
111 if (cache_
->GetStatistics(&cache_size
, &extensions_count
)) {
112 UMA_HISTOGRAM_COUNTS_100("Extensions.ExtensionCacheCount",
114 UMA_HISTOGRAM_MEMORY_MB("Extensions.ExtensionCacheSize",
115 cache_size
/ (1024 * 1024));
119 void ExtensionCacheImpl::Observe(int type
,
120 const content::NotificationSource
& source
,
121 const content::NotificationDetails
& details
) {
126 case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR
: {
127 extensions::CrxInstaller
* installer
=
128 content::Source
<extensions::CrxInstaller
>(source
).ptr();
129 // TODO(dpolukhin): remove extension from cache only if installation
130 // failed due to file corruption.
131 cache_
->RemoveExtension(installer
->expected_id());
140 } // namespace extensions