| Index: chrome/browser/browsing_data_remover_unittest.cc | 
| diff --git a/chrome/browser/browsing_data_remover_unittest.cc b/chrome/browser/browsing_data_remover_unittest.cc | 
| index e55e87b1976a19a3d236f0fcab3f13c6bcfed299..9ca2472dee3bf1baaff2cb3c7993497ac055ea61 100644 | 
| --- a/chrome/browser/browsing_data_remover_unittest.cc | 
| +++ b/chrome/browser/browsing_data_remover_unittest.cc | 
| @@ -4,18 +4,25 @@ | 
|  | 
| #include "chrome/browser/browsing_data_remover.h" | 
|  | 
| +#include <set> | 
| + | 
| #include "base/message_loop.h" | 
| #include "base/platform_file.h" | 
| #include "chrome/browser/history/history.h" | 
| #include "chrome/test/testing_profile.h" | 
| +#include "content/browser/appcache/chrome_appcache_service.h" | 
| #include "testing/gtest/include/gtest/gtest.h" | 
| +#include "webkit/appcache/appcache.h" | 
| +#include "webkit/appcache/appcache_group.h" | 
| +#include "webkit/appcache/appcache_storage.h" | 
| #include "webkit/fileapi/file_system_context.h" | 
| #include "webkit/fileapi/file_system_operation_context.h" | 
| #include "webkit/fileapi/file_system_file_util.h" | 
| #include "webkit/fileapi/file_system_path_manager.h" | 
| #include "webkit/fileapi/sandbox_mount_point_provider.h" | 
| +#include "webkit/quota/mock_special_storage_policy.h" | 
|  | 
| -namespace { | 
| +namespace browsing_data_remover_test { | 
|  | 
| const char kTestkOrigin1[] = "http://host1:1/"; | 
| const char kTestkOrigin2[] = "http://host2:1/"; | 
| @@ -25,6 +32,9 @@ const GURL kOrigin1(kTestkOrigin1); | 
| const GURL kOrigin2(kTestkOrigin2); | 
| const GURL kOrigin3(kTestkOrigin3); | 
|  | 
| +const GURL kProtectedManifest("http://www.protected.com/cache.manifest"); | 
| +const GURL kNormalManifest("http://www.normal.com/cache.manifest"); | 
| + | 
| class BrowsingDataRemoverTester : public BrowsingDataRemover::Observer { | 
| public: | 
| BrowsingDataRemoverTester() {} | 
| @@ -156,6 +166,82 @@ class RemoveFileSystemTester : public BrowsingDataRemoverTester { | 
| DISALLOW_COPY_AND_ASSIGN(RemoveFileSystemTester); | 
| }; | 
|  | 
| +// Helper class for injecting data into AppCacheStorage. | 
| +class DummyStorageDelegate : public appcache::AppCacheStorage::Delegate { | 
| + public: | 
| +  DummyStorageDelegate() { } | 
| +  virtual void OnGroupAndNewestCacheStored( | 
| +      appcache::AppCacheGroup* /*group*/, appcache::AppCache* /*newest_cache*/, | 
| +      bool success, bool /*would_exceed_quota*/) { | 
| +    EXPECT_TRUE(success); | 
| +    MessageLoop::current()->Quit(); | 
| +  } | 
| +}; | 
| + | 
| +void AddGroupAndCache(ChromeAppCacheService* appcache_service, | 
| +                      const GURL& manifest_url) { | 
| + | 
| +  using appcache::AppCache; | 
| +  using appcache::AppCacheEntry; | 
| +  using appcache::AppCacheGroup; | 
| +  static int group_id = 0; | 
| +  static int appcache_id = 0; | 
| +  static int response_id = 0; | 
| +  AppCacheGroup* appcache_group = | 
| +      new AppCacheGroup(appcache_service, manifest_url, ++group_id); | 
| +  AppCache* appcache = new appcache::AppCache(appcache_service, ++appcache_id); | 
| +  AppCacheEntry entry(AppCacheEntry::MANIFEST, ++response_id); | 
| +  appcache->AddEntry(manifest_url, entry); | 
| +  appcache->set_complete(true); | 
| +  appcache_group->AddCache(appcache); | 
| +  DummyStorageDelegate test_delegate; | 
| +  appcache_service->storage()->StoreGroupAndNewestCache(appcache_group, | 
| +                                                        appcache, | 
| +                                                        &test_delegate); | 
| +  // DummyStorageDelegate::OnGroupAndNewestCacheStored will quit the message | 
| +  // loop. | 
| +  MessageLoop::current()->Run(); | 
| +} | 
| + | 
| +// Helper class for reading appcaches. | 
| +class AppCacheReader { | 
| +public: | 
| +  explicit AppCacheReader(ChromeAppCacheService* appcache_service) | 
| +    : appcache_service_(appcache_service), | 
| +      ALLOW_THIS_IN_INITIALIZER_LIST(appcache_got_info_callback_( | 
| +          this, &AppCacheReader::OnGotAppCacheInfo)) { | 
| +  } | 
| + | 
| +  std::set<GURL>* ReadAppCaches() { | 
| +    appcache_info_ = new appcache::AppCacheInfoCollection; | 
| +    appcache_service_->GetAllAppCacheInfo( | 
| +        appcache_info_, &appcache_got_info_callback_); | 
| + | 
| +    MessageLoop::current()->Run(); | 
| +    return &origins_; | 
| +  } | 
| + | 
| +private: | 
| +  void OnGotAppCacheInfo(int rv) { | 
| +    using appcache::AppCacheInfoVector; | 
| +    typedef std::map<GURL, AppCacheInfoVector> InfoByOrigin; | 
| + | 
| +    origins_.clear(); | 
| +    for (InfoByOrigin::const_iterator origin = | 
| +             appcache_info_->infos_by_origin.begin(); | 
| +         origin != appcache_info_->infos_by_origin.end(); ++origin) { | 
| +      origins_.insert(origin->first); | 
| +    } | 
| +    MessageLoop::current()->Quit(); | 
| +  } | 
| + | 
| +  scoped_refptr<ChromeAppCacheService> appcache_service_; | 
| +  net::CompletionCallbackImpl<AppCacheReader> | 
| +      appcache_got_info_callback_; | 
| +  scoped_refptr<appcache::AppCacheInfoCollection> appcache_info_; | 
| +  std::set<GURL> origins_; | 
| +}; | 
| + | 
| class BrowsingDataRemoverTest : public testing::Test { | 
| public: | 
| BrowsingDataRemoverTest() | 
| @@ -264,4 +350,53 @@ TEST_F(BrowsingDataRemoverTest, RemoveFileSystemsForever) { | 
| fileapi::kFileSystemTypeTemporary)); | 
| } | 
|  | 
| -}  // namespace | 
| + | 
| +TEST_F(BrowsingDataRemoverTest, RemoveAppCacheForever) { | 
| +  // Set up ChromeAppCacheService. | 
| +  scoped_refptr<ChromeAppCacheService> appcache_service = | 
| +      new ChromeAppCacheService(NULL); | 
| +  const content::ResourceContext* resource_context = NULL; | 
| +  scoped_refptr<quota::MockSpecialStoragePolicy> mock_policy = | 
| +      new quota::MockSpecialStoragePolicy; | 
| +  mock_policy->AddProtected(kProtectedManifest.GetOrigin()); | 
| +  BrowserThread::PostTask( | 
| +      BrowserThread::IO, FROM_HERE, | 
| +      NewRunnableMethod(appcache_service.get(), | 
| +                        &ChromeAppCacheService::InitializeOnIOThread, | 
| +                        FilePath(""), | 
| +                        resource_context, | 
| +                        mock_policy)); | 
| +  MessageLoop::current()->RunAllPending(); | 
| +  TestingProfile* profile = GetProfile(); | 
| +  profile->SetAppCacheService(appcache_service); | 
| + | 
| +  // Add data into the AppCacheStorage. | 
| +  AddGroupAndCache(appcache_service, kNormalManifest); | 
| +  AddGroupAndCache(appcache_service, kProtectedManifest); | 
| + | 
| +  // Verify that adding the data succeeded. | 
| +  scoped_ptr<AppCacheReader> reader(new AppCacheReader(appcache_service)); | 
| +  std::set<GURL>* origins = reader->ReadAppCaches(); | 
| +  EXPECT_EQ(2UL, origins->size()); | 
| +  EXPECT_NE(origins->end(), origins->find(kProtectedManifest.GetOrigin())); | 
| +  EXPECT_NE(origins->end(), origins->find(kNormalManifest.GetOrigin())); | 
| + | 
| +  // Set up the object to be tested. | 
| +  scoped_ptr<BrowsingDataRemoverTester> tester(new BrowsingDataRemoverTester()); | 
| +  BrowsingDataRemover* remover = new BrowsingDataRemover( | 
| +    profile, BrowsingDataRemover::EVERYTHING, base::Time::Now()); | 
| +  remover->AddObserver(tester.get()); | 
| + | 
| +  // Remove the appcaches and wait for it to complete. BrowsingDataRemover | 
| +  // deletes itself when it completes. | 
| +  remover->Remove(BrowsingDataRemover::REMOVE_COOKIES); | 
| +  tester->BlockUntilNotified(); | 
| + | 
| +  // Results: appcaches for the normal origin got deleted, appcaches for the | 
| +  // protected origin didn't. | 
| +  origins = reader->ReadAppCaches(); | 
| +  EXPECT_EQ(1UL, origins->size()); | 
| +  EXPECT_NE(origins->end(), origins->find(kProtectedManifest.GetOrigin())); | 
| +} | 
| + | 
| +}  // namespace browsing_data_remover_test | 
|  |