Home | History | Annotate | Download | only in appcache
      1 // Copyright (c) 2012 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.
      4 
      5 #include "base/bind.h"
      6 #include "base/file_util.h"
      7 #include "base/files/scoped_temp_dir.h"
      8 #include "base/memory/ref_counted.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "content/browser/appcache/chrome_appcache_service.h"
     11 #include "content/browser/browser_thread_impl.h"
     12 #include "content/public/browser/resource_context.h"
     13 #include "content/public/test/mock_special_storage_policy.h"
     14 #include "content/public/test/test_browser_context.h"
     15 #include "content/test/appcache_test_helper.h"
     16 #include "net/url_request/url_request_context_getter.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 #include "webkit/browser/appcache/appcache_database.h"
     19 #include "webkit/browser/appcache/appcache_storage_impl.h"
     20 
     21 #include <set>
     22 
     23 namespace content {
     24 namespace {
     25 const base::FilePath::CharType kTestingAppCacheDirname[] =
     26     FILE_PATH_LITERAL("Application Cache");
     27 
     28 // Examples of a protected and an unprotected origin, to be used througout the
     29 // test.
     30 const char kProtectedManifest[] = "http://www.protected.com/cache.manifest";
     31 const char kNormalManifest[] = "http://www.normal.com/cache.manifest";
     32 const char kSessionOnlyManifest[] = "http://www.sessiononly.com/cache.manifest";
     33 
     34 class MockURLRequestContextGetter : public net::URLRequestContextGetter {
     35  public:
     36   MockURLRequestContextGetter(
     37       net::URLRequestContext* context,
     38       base::MessageLoopProxy* message_loop_proxy)
     39       : context_(context), message_loop_proxy_(message_loop_proxy) {
     40   }
     41 
     42   virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE {
     43     return context_;
     44   }
     45 
     46   virtual scoped_refptr<base::SingleThreadTaskRunner>
     47       GetNetworkTaskRunner() const OVERRIDE {
     48     return message_loop_proxy_;
     49   }
     50 
     51  protected:
     52   virtual ~MockURLRequestContextGetter() {}
     53 
     54  private:
     55   net::URLRequestContext* context_;
     56   scoped_refptr<base::SingleThreadTaskRunner> message_loop_proxy_;
     57 };
     58 
     59 }  // namespace
     60 
     61 class ChromeAppCacheServiceTest : public testing::Test {
     62  public:
     63   ChromeAppCacheServiceTest()
     64       : kProtectedManifestURL(kProtectedManifest),
     65         kNormalManifestURL(kNormalManifest),
     66         kSessionOnlyManifestURL(kSessionOnlyManifest),
     67         file_thread_(BrowserThread::FILE, &message_loop_),
     68         file_user_blocking_thread_(BrowserThread::FILE_USER_BLOCKING,
     69                                    &message_loop_),
     70         cache_thread_(BrowserThread::CACHE, &message_loop_),
     71         io_thread_(BrowserThread::IO, &message_loop_) {}
     72 
     73  protected:
     74   scoped_refptr<ChromeAppCacheService> CreateAppCacheServiceImpl(
     75       const base::FilePath& appcache_path,
     76       bool init_storage);
     77   void InsertDataIntoAppCache(ChromeAppCacheService* appcache_service);
     78 
     79   base::MessageLoopForIO message_loop_;
     80   base::ScopedTempDir temp_dir_;
     81   const GURL kProtectedManifestURL;
     82   const GURL kNormalManifestURL;
     83   const GURL kSessionOnlyManifestURL;
     84 
     85  private:
     86   BrowserThreadImpl file_thread_;
     87   BrowserThreadImpl file_user_blocking_thread_;
     88   BrowserThreadImpl cache_thread_;
     89   BrowserThreadImpl io_thread_;
     90   TestBrowserContext browser_context_;
     91 };
     92 
     93 scoped_refptr<ChromeAppCacheService>
     94 ChromeAppCacheServiceTest::CreateAppCacheServiceImpl(
     95     const base::FilePath& appcache_path,
     96     bool init_storage) {
     97   scoped_refptr<ChromeAppCacheService> appcache_service =
     98       new ChromeAppCacheService(NULL);
     99   scoped_refptr<MockSpecialStoragePolicy> mock_policy =
    100       new MockSpecialStoragePolicy;
    101   mock_policy->AddProtected(kProtectedManifestURL.GetOrigin());
    102   mock_policy->AddSessionOnly(kSessionOnlyManifestURL.GetOrigin());
    103   scoped_refptr<MockURLRequestContextGetter> mock_request_context_getter =
    104       new MockURLRequestContextGetter(
    105           browser_context_.GetResourceContext()->GetRequestContext(),
    106           message_loop_.message_loop_proxy().get());
    107   BrowserThread::PostTask(
    108       BrowserThread::IO,
    109       FROM_HERE,
    110       base::Bind(&ChromeAppCacheService::InitializeOnIOThread,
    111                  appcache_service.get(),
    112                  appcache_path,
    113                  browser_context_.GetResourceContext(),
    114                  mock_request_context_getter,
    115                  mock_policy));
    116   // Steps needed to initialize the storage of AppCache data.
    117   message_loop_.RunUntilIdle();
    118   if (init_storage) {
    119     appcache::AppCacheStorageImpl* storage =
    120         static_cast<appcache::AppCacheStorageImpl*>(
    121             appcache_service->storage());
    122     storage->database_->db_connection();
    123     storage->disk_cache();
    124     message_loop_.RunUntilIdle();
    125   }
    126   return appcache_service;
    127 }
    128 
    129 void ChromeAppCacheServiceTest::InsertDataIntoAppCache(
    130     ChromeAppCacheService* appcache_service) {
    131   AppCacheTestHelper appcache_helper;
    132   appcache_helper.AddGroupAndCache(appcache_service, kNormalManifestURL);
    133   appcache_helper.AddGroupAndCache(appcache_service, kProtectedManifestURL);
    134   appcache_helper.AddGroupAndCache(appcache_service, kSessionOnlyManifestURL);
    135 
    136   // Verify that adding the data succeeded
    137   std::set<GURL> origins;
    138   appcache_helper.GetOriginsWithCaches(appcache_service, &origins);
    139   ASSERT_EQ(3UL, origins.size());
    140   ASSERT_TRUE(origins.find(kProtectedManifestURL.GetOrigin()) != origins.end());
    141   ASSERT_TRUE(origins.find(kNormalManifestURL.GetOrigin()) != origins.end());
    142   ASSERT_TRUE(origins.find(kSessionOnlyManifestURL.GetOrigin()) !=
    143               origins.end());
    144 }
    145 
    146 TEST_F(ChromeAppCacheServiceTest, KeepOnDestruction) {
    147   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    148   base::FilePath appcache_path =
    149       temp_dir_.path().Append(kTestingAppCacheDirname);
    150 
    151   // Create a ChromeAppCacheService and insert data into it
    152   scoped_refptr<ChromeAppCacheService> appcache_service =
    153       CreateAppCacheServiceImpl(appcache_path, true);
    154   ASSERT_TRUE(base::PathExists(appcache_path));
    155   ASSERT_TRUE(base::PathExists(appcache_path.AppendASCII("Index")));
    156   InsertDataIntoAppCache(appcache_service.get());
    157 
    158   // Test: delete the ChromeAppCacheService
    159   appcache_service = NULL;
    160   message_loop_.RunUntilIdle();
    161 
    162   // Recreate the appcache (for reading the data back)
    163   appcache_service = CreateAppCacheServiceImpl(appcache_path, false);
    164 
    165   // The directory is still there
    166   ASSERT_TRUE(base::PathExists(appcache_path));
    167 
    168   // The appcache data is also there, except the session-only origin.
    169   AppCacheTestHelper appcache_helper;
    170   std::set<GURL> origins;
    171   appcache_helper.GetOriginsWithCaches(appcache_service.get(), &origins);
    172   EXPECT_EQ(2UL, origins.size());
    173   EXPECT_TRUE(origins.find(kProtectedManifestURL.GetOrigin()) != origins.end());
    174   EXPECT_TRUE(origins.find(kNormalManifestURL.GetOrigin()) != origins.end());
    175   EXPECT_TRUE(origins.find(kSessionOnlyManifestURL.GetOrigin()) ==
    176               origins.end());
    177 
    178   // Delete and let cleanup tasks run prior to returning.
    179   appcache_service = NULL;
    180   message_loop_.RunUntilIdle();
    181 }
    182 
    183 TEST_F(ChromeAppCacheServiceTest, SaveSessionState) {
    184   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    185   base::FilePath appcache_path =
    186       temp_dir_.path().Append(kTestingAppCacheDirname);
    187 
    188   // Create a ChromeAppCacheService and insert data into it
    189   scoped_refptr<ChromeAppCacheService> appcache_service =
    190       CreateAppCacheServiceImpl(appcache_path, true);
    191   ASSERT_TRUE(base::PathExists(appcache_path));
    192   ASSERT_TRUE(base::PathExists(appcache_path.AppendASCII("Index")));
    193   InsertDataIntoAppCache(appcache_service.get());
    194 
    195   // Save session state. This should bypass the destruction-time deletion.
    196   appcache_service->set_force_keep_session_state();
    197 
    198   // Test: delete the ChromeAppCacheService
    199   appcache_service = NULL;
    200   message_loop_.RunUntilIdle();
    201 
    202   // Recreate the appcache (for reading the data back)
    203   appcache_service = CreateAppCacheServiceImpl(appcache_path, false);
    204 
    205   // The directory is still there
    206   ASSERT_TRUE(base::PathExists(appcache_path));
    207 
    208   // No appcache data was deleted.
    209   AppCacheTestHelper appcache_helper;
    210   std::set<GURL> origins;
    211   appcache_helper.GetOriginsWithCaches(appcache_service.get(), &origins);
    212   EXPECT_EQ(3UL, origins.size());
    213   EXPECT_TRUE(origins.find(kProtectedManifestURL.GetOrigin()) != origins.end());
    214   EXPECT_TRUE(origins.find(kNormalManifestURL.GetOrigin()) != origins.end());
    215   EXPECT_TRUE(origins.find(kSessionOnlyManifestURL.GetOrigin()) !=
    216               origins.end());
    217 
    218   // Delete and let cleanup tasks run prior to returning.
    219   appcache_service = NULL;
    220   message_loop_.RunUntilIdle();
    221 }
    222 
    223 }  // namespace content
    224