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