1e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// found in the LICENSE file. 4e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 5e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/browser/extensions/extension_garbage_collector.h" 6e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 7e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/bind.h" 8e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/files/file_enumerator.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 10e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/logging.h" 11e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/memory/scoped_ptr.h" 12e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/message_loop/message_loop.h" 13e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/sequenced_task_runner.h" 14e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/strings/string_util.h" 15e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/strings/utf_string_conversions.h" 16e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/time/time.h" 170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "chrome/browser/extensions/extension_garbage_collector_factory.h" 18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/browser/extensions/extension_service.h" 19e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/browser/extensions/extension_util.h" 200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "chrome/browser/extensions/install_tracker.h" 21e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/browser/extensions/pending_extension_manager.h" 22e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/common/extensions/manifest_handlers/app_isolation_info.h" 2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/crx_file/id_util.h" 24e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "content/public/browser/browser_context.h" 25e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "content/public/browser/browser_thread.h" 26e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "content/public/browser/storage_partition.h" 27e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "extensions/browser/extension_prefs.h" 28e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "extensions/browser/extension_registry.h" 29e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "extensions/browser/extension_system.h" 30e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "extensions/common/extension.h" 31a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/common/file_util.h" 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/one_shot_event.h" 33e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 34e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochnamespace extensions { 35e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 36e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochnamespace { 37e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 38e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Wait this many seconds before trying to garbage collect extensions again. 39e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst int kGarbageCollectRetryDelayInSeconds = 30; 40e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 41e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Wait this many seconds after startup to see if there are any extensions 42e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// which can be garbage collected. 43e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst int kGarbageCollectStartupDelay = 30; 44e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 45e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochtypedef std::multimap<std::string, base::FilePath> ExtensionPathsMultimap; 46e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 47e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid CheckExtensionDirectory(const base::FilePath& path, 480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const ExtensionPathsMultimap& extension_paths) { 49e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::FilePath basename = path.BaseName(); 50e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Clean up temporary files left if Chrome crashed or quit in the middle 51e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // of an extension install. 52a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (basename.value() == file_util::kTempDirectoryName) { 530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::DeleteFile(path, true); // Recursive. 54e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Parse directory name as a potential extension ID. 58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::string extension_id; 59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (base::IsStringASCII(basename.value())) { 60e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extension_id = base::UTF16ToASCII(basename.LossyDisplayName()); 6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!crx_file::id_util::IdIsValid(extension_id)) 62e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extension_id.clear(); 63e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 64e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 65e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Delete directories that aren't valid IDs. 66e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (extension_id.empty()) { 67e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::DeleteFile(path, true); // Recursive. 68e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 69e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 70e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 71e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch typedef ExtensionPathsMultimap::const_iterator Iter; 72e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::pair<Iter, Iter> iter_pair = extension_paths.equal_range(extension_id); 73e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 74e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // If there is no entry in the prefs file, just delete the directory and 75e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // move on. This can legitimately happen when an uninstall does not 76e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // complete, for example, when a plugin is in use at uninstall time. 77e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (iter_pair.first == iter_pair.second) { 78e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::DeleteFile(path, true); // Recursive. 79e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 80e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 81e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Clean up old version directories. 83e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::FileEnumerator versions_enumerator( 84e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch path, false /* Not recursive */, base::FileEnumerator::DIRECTORIES); 85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch for (base::FilePath version_dir = versions_enumerator.Next(); 86e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch !version_dir.empty(); 87e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch version_dir = versions_enumerator.Next()) { 88e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bool known_version = false; 89e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch for (Iter iter = iter_pair.first; iter != iter_pair.second; ++iter) { 90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (version_dir.BaseName() == iter->second.BaseName()) { 91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch known_version = true; 92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch break; 93e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 95e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (!known_version) 96e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::DeleteFile(version_dir, true); // Recursive. 97e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 98e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 99e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 100e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} // namespace 101e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 102e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochExtensionGarbageCollector::ExtensionGarbageCollector( 1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch content::BrowserContext* context) 1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : context_(context), crx_installs_in_progress_(0), weak_factory_(this) { 105e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 106e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ExtensionSystem* extension_system = ExtensionSystem::Get(context_); 107e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(extension_system); 108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 109e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extension_system->ready().PostDelayed( 110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch FROM_HERE, 111e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&ExtensionGarbageCollector::GarbageCollectExtensions, 112e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_factory_.GetWeakPtr()), 113e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::TimeDelta::FromSeconds(kGarbageCollectStartupDelay)); 114e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 115e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extension_system->ready().Post( 116e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch FROM_HERE, 117e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind( 118e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch &ExtensionGarbageCollector::GarbageCollectIsolatedStorageIfNeeded, 119e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_factory_.GetWeakPtr())); 1200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch InstallTracker::Get(context_)->AddObserver(this); 122e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 123e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 124e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochExtensionGarbageCollector::~ExtensionGarbageCollector() {} 125e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// static 1270529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochExtensionGarbageCollector* ExtensionGarbageCollector::Get( 1280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch content::BrowserContext* context) { 1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return ExtensionGarbageCollectorFactory::GetForBrowserContext(context); 1300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ExtensionGarbageCollector::Shutdown() { 1330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch InstallTracker::Get(context_)->RemoveObserver(this); 1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 136e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid ExtensionGarbageCollector::GarbageCollectExtensionsForTest() { 137e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch GarbageCollectExtensions(); 138e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 139e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ExtensionGarbageCollector::GarbageCollectExtensionsOnFileThread( 14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const base::FilePath& install_directory, 14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const ExtensionPathsMultimap& extension_paths) { 14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 145e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Nothing to clean up if it doesn't exist. 14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!base::DirectoryExists(install_directory)) 148e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::FileEnumerator enumerator(install_directory, 15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) false, // Not recursive. 15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::FileEnumerator::DIRECTORIES); 15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (base::FilePath extension_path = enumerator.Next(); 15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) !extension_path.empty(); 15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension_path = enumerator.Next()) { 15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CheckExtensionDirectory(extension_path, extension_paths); 15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ExtensionGarbageCollector::GarbageCollectExtensions() { 16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 163e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 164e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(context_); 165e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(extension_prefs); 166e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 167e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (extension_prefs->pref_service()->ReadOnly()) 168e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 169e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (crx_installs_in_progress_ > 0) { 1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Don't garbage collect while there are installations in progress, 172e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // which may be using the temporary installation directory. Try to garbage 173e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // collect again later. 174e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::MessageLoop::current()->PostDelayedTask( 175e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch FROM_HERE, 176e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&ExtensionGarbageCollector::GarbageCollectExtensions, 177e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch weak_factory_.GetWeakPtr()), 178e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::TimeDelta::FromSeconds(kGarbageCollectRetryDelayInSeconds)); 1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 180e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 181e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 182e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<ExtensionPrefs::ExtensionsInfo> info( 183e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extension_prefs->GetInstalledExtensionsInfo()); 184e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::multimap<std::string, base::FilePath> extension_paths; 185e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch for (size_t i = 0; i < info->size(); ++i) { 186e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extension_paths.insert( 187e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::make_pair(info->at(i)->extension_id, info->at(i)->extension_path)); 188e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 189e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 190e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch info = extension_prefs->GetAllDelayedInstallInfo(); 191e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch for (size_t i = 0; i < info->size(); ++i) { 192e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extension_paths.insert( 193e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::make_pair(info->at(i)->extension_id, info->at(i)->extension_path)); 194e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 195e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ExtensionService* service = 1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ExtensionSystem::Get(context_)->extension_service(); 1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!service->GetFileTaskRunner()->PostTask( 199e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch FROM_HERE, 2000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Bind(&GarbageCollectExtensionsOnFileThread, 2010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch service->install_directory(), 2020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch extension_paths))) { 203e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch NOTREACHED(); 204e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 205e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 206e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 207e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid ExtensionGarbageCollector::GarbageCollectIsolatedStorageIfNeeded() { 208e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 209e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 210e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(context_); 211e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(extension_prefs); 212e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (!extension_prefs->NeedsStorageGarbageCollection()) 213e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 214e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extension_prefs->SetNeedsStorageGarbageCollection(false); 215e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 216e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<base::hash_set<base::FilePath> > active_paths( 217e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch new base::hash_set<base::FilePath>()); 2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<ExtensionSet> extensions = 2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ExtensionRegistry::Get(context_)->GenerateInstalledExtensionsSet(); 2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (ExtensionSet::const_iterator iter = extensions->begin(); 2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu iter != extensions->end(); 222e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ++iter) { 223e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (AppIsolationInfo::HasIsolatedStorage(iter->get())) { 224e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch active_paths->insert( 225e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch content::BrowserContext::GetStoragePartitionForSite( 226e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch context_, util::GetSiteForExtensionId((*iter)->id(), context_)) 227e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ->GetPath()); 228e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 229e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 230e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 2310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ExtensionService* service = 2320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ExtensionSystem::Get(context_)->extension_service(); 2330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch service->OnGarbageCollectIsolatedStorageStart(); 234e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch content::BrowserContext::GarbageCollectStoragePartitions( 235e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch context_, 236e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch active_paths.Pass(), 237e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&ExtensionService::OnGarbageCollectIsolatedStorageFinished, 2380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch service->AsWeakPtr())); 2390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 2400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ExtensionGarbageCollector::OnBeginCrxInstall( 2420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::string& extension_id) { 2430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch crx_installs_in_progress_++; 2440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 2450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid ExtensionGarbageCollector::OnFinishCrxInstall( 2470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const std::string& extension_id, 2480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool success) { 2490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch crx_installs_in_progress_--; 2500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (crx_installs_in_progress_ < 0) { 2510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // This can only happen if there is a mismatch in our begin/finish 2520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // accounting. 2530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch NOTREACHED(); 2540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Don't let the count go negative to avoid garbage collecting when 2560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // an install is actually in progress. 2570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch crx_installs_in_progress_ = 0; 2580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 259e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 260e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 261e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} // namespace extensions 262