1// Copyright (c) 2011 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 <map> 6 7#include "base/bind.h" 8#include "base/files/file_path.h" 9#include "base/files/file_util.h" 10#include "base/files/scoped_temp_dir.h" 11#include "base/message_loop/message_loop.h" 12#include "base/test/test_simple_task_runner.h" 13#include "base/threading/thread.h" 14#include "content/browser/browser_thread_impl.h" 15#include "content/browser/indexed_db/indexed_db_context_impl.h" 16#include "content/browser/indexed_db/indexed_db_quota_client.h" 17#include "content/browser/quota/mock_quota_manager.h" 18#include "content/public/browser/storage_partition.h" 19#include "content/public/test/test_browser_context.h" 20#include "content/public/test/test_browser_thread_bundle.h" 21#include "storage/common/database/database_identifier.h" 22#include "testing/gtest/include/gtest/gtest.h" 23 24// Declared to shorten the line lengths. 25static const storage::StorageType kTemp = storage::kStorageTypeTemporary; 26static const storage::StorageType kPerm = storage::kStorageTypePersistent; 27 28namespace content { 29 30// Base class for our test fixtures. 31class IndexedDBQuotaClientTest : public testing::Test { 32 public: 33 const GURL kOriginA; 34 const GURL kOriginB; 35 const GURL kOriginOther; 36 37 IndexedDBQuotaClientTest() 38 : kOriginA("http://host"), 39 kOriginB("http://host:8000"), 40 kOriginOther("http://other"), 41 usage_(0), 42 task_runner_(new base::TestSimpleTaskRunner), 43 weak_factory_(this) { 44 browser_context_.reset(new TestBrowserContext()); 45 46 scoped_refptr<storage::QuotaManager> quota_manager = 47 new MockQuotaManager(false /*in_memory*/, 48 browser_context_->GetPath(), 49 base::MessageLoop::current()->message_loop_proxy(), 50 base::MessageLoop::current()->message_loop_proxy(), 51 browser_context_->GetSpecialStoragePolicy()); 52 53 idb_context_ = 54 new IndexedDBContextImpl(browser_context_->GetPath(), 55 browser_context_->GetSpecialStoragePolicy(), 56 quota_manager->proxy(), 57 task_runner_.get()); 58 base::MessageLoop::current()->RunUntilIdle(); 59 setup_temp_dir(); 60 } 61 62 void FlushIndexedDBTaskRunner() { task_runner_->RunUntilIdle(); } 63 64 void setup_temp_dir() { 65 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 66 base::FilePath indexeddb_dir = 67 temp_dir_.path().Append(IndexedDBContextImpl::kIndexedDBDirectory); 68 ASSERT_TRUE(base::CreateDirectory(indexeddb_dir)); 69 idb_context()->set_data_path_for_testing(indexeddb_dir); 70 } 71 72 virtual ~IndexedDBQuotaClientTest() { 73 FlushIndexedDBTaskRunner(); 74 idb_context_ = NULL; 75 browser_context_.reset(); 76 base::MessageLoop::current()->RunUntilIdle(); 77 } 78 79 int64 GetOriginUsage(storage::QuotaClient* client, 80 const GURL& origin, 81 storage::StorageType type) { 82 usage_ = -1; 83 client->GetOriginUsage( 84 origin, 85 type, 86 base::Bind(&IndexedDBQuotaClientTest::OnGetOriginUsageComplete, 87 weak_factory_.GetWeakPtr())); 88 FlushIndexedDBTaskRunner(); 89 base::MessageLoop::current()->RunUntilIdle(); 90 EXPECT_GT(usage_, -1); 91 return usage_; 92 } 93 94 const std::set<GURL>& GetOriginsForType(storage::QuotaClient* client, 95 storage::StorageType type) { 96 origins_.clear(); 97 client->GetOriginsForType( 98 type, 99 base::Bind(&IndexedDBQuotaClientTest::OnGetOriginsComplete, 100 weak_factory_.GetWeakPtr())); 101 FlushIndexedDBTaskRunner(); 102 base::MessageLoop::current()->RunUntilIdle(); 103 return origins_; 104 } 105 106 const std::set<GURL>& GetOriginsForHost(storage::QuotaClient* client, 107 storage::StorageType type, 108 const std::string& host) { 109 origins_.clear(); 110 client->GetOriginsForHost( 111 type, 112 host, 113 base::Bind(&IndexedDBQuotaClientTest::OnGetOriginsComplete, 114 weak_factory_.GetWeakPtr())); 115 FlushIndexedDBTaskRunner(); 116 base::MessageLoop::current()->RunUntilIdle(); 117 return origins_; 118 } 119 120 storage::QuotaStatusCode DeleteOrigin(storage::QuotaClient* client, 121 const GURL& origin_url) { 122 delete_status_ = storage::kQuotaStatusUnknown; 123 client->DeleteOriginData( 124 origin_url, 125 kTemp, 126 base::Bind(&IndexedDBQuotaClientTest::OnDeleteOriginComplete, 127 weak_factory_.GetWeakPtr())); 128 FlushIndexedDBTaskRunner(); 129 base::MessageLoop::current()->RunUntilIdle(); 130 return delete_status_; 131 } 132 133 IndexedDBContextImpl* idb_context() { return idb_context_.get(); } 134 135 void SetFileSizeTo(const base::FilePath& path, int size) { 136 std::string junk(size, 'a'); 137 ASSERT_EQ(size, base::WriteFile(path, junk.c_str(), size)); 138 } 139 140 void AddFakeIndexedDB(const GURL& origin, int size) { 141 base::FilePath file_path_origin = idb_context()->GetFilePathForTesting( 142 storage::GetIdentifierFromOrigin(origin)); 143 if (!base::CreateDirectory(file_path_origin)) { 144 LOG(ERROR) << "failed to base::CreateDirectory " 145 << file_path_origin.value(); 146 } 147 file_path_origin = file_path_origin.Append(FILE_PATH_LITERAL("fake_file")); 148 SetFileSizeTo(file_path_origin, size); 149 idb_context()->ResetCaches(); 150 } 151 152 private: 153 void OnGetOriginUsageComplete(int64 usage) { usage_ = usage; } 154 155 void OnGetOriginsComplete(const std::set<GURL>& origins) { 156 origins_ = origins; 157 } 158 159 void OnDeleteOriginComplete(storage::QuotaStatusCode code) { 160 delete_status_ = code; 161 } 162 163 base::ScopedTempDir temp_dir_; 164 int64 usage_; 165 std::set<GURL> origins_; 166 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; 167 scoped_refptr<IndexedDBContextImpl> idb_context_; 168 content::TestBrowserThreadBundle thread_bundle_; 169 scoped_ptr<TestBrowserContext> browser_context_; 170 storage::QuotaStatusCode delete_status_; 171 base::WeakPtrFactory<IndexedDBQuotaClientTest> weak_factory_; 172 173 DISALLOW_COPY_AND_ASSIGN(IndexedDBQuotaClientTest); 174}; 175 176TEST_F(IndexedDBQuotaClientTest, GetOriginUsage) { 177 IndexedDBQuotaClient client(idb_context()); 178 179 AddFakeIndexedDB(kOriginA, 6); 180 AddFakeIndexedDB(kOriginB, 3); 181 EXPECT_EQ(6, GetOriginUsage(&client, kOriginA, kTemp)); 182 EXPECT_EQ(0, GetOriginUsage(&client, kOriginA, kPerm)); 183 EXPECT_EQ(3, GetOriginUsage(&client, kOriginB, kTemp)); 184 EXPECT_EQ(0, GetOriginUsage(&client, kOriginB, kPerm)); 185 186 AddFakeIndexedDB(kOriginA, 1000); 187 EXPECT_EQ(1000, GetOriginUsage(&client, kOriginA, kTemp)); 188 EXPECT_EQ(0, GetOriginUsage(&client, kOriginA, kPerm)); 189 EXPECT_EQ(3, GetOriginUsage(&client, kOriginB, kTemp)); 190 EXPECT_EQ(0, GetOriginUsage(&client, kOriginB, kPerm)); 191} 192 193TEST_F(IndexedDBQuotaClientTest, GetOriginsForHost) { 194 IndexedDBQuotaClient client(idb_context()); 195 196 EXPECT_EQ(kOriginA.host(), kOriginB.host()); 197 EXPECT_NE(kOriginA.host(), kOriginOther.host()); 198 199 std::set<GURL> origins = GetOriginsForHost(&client, kTemp, kOriginA.host()); 200 EXPECT_TRUE(origins.empty()); 201 202 AddFakeIndexedDB(kOriginA, 1000); 203 origins = GetOriginsForHost(&client, kTemp, kOriginA.host()); 204 EXPECT_EQ(origins.size(), 1ul); 205 EXPECT_TRUE(origins.find(kOriginA) != origins.end()); 206 207 AddFakeIndexedDB(kOriginB, 1000); 208 origins = GetOriginsForHost(&client, kTemp, kOriginA.host()); 209 EXPECT_EQ(origins.size(), 2ul); 210 EXPECT_TRUE(origins.find(kOriginA) != origins.end()); 211 EXPECT_TRUE(origins.find(kOriginB) != origins.end()); 212 213 EXPECT_TRUE(GetOriginsForHost(&client, kPerm, kOriginA.host()).empty()); 214 EXPECT_TRUE(GetOriginsForHost(&client, kTemp, kOriginOther.host()).empty()); 215} 216 217TEST_F(IndexedDBQuotaClientTest, GetOriginsForType) { 218 IndexedDBQuotaClient client(idb_context()); 219 220 EXPECT_TRUE(GetOriginsForType(&client, kTemp).empty()); 221 EXPECT_TRUE(GetOriginsForType(&client, kPerm).empty()); 222 223 AddFakeIndexedDB(kOriginA, 1000); 224 std::set<GURL> origins = GetOriginsForType(&client, kTemp); 225 EXPECT_EQ(origins.size(), 1ul); 226 EXPECT_TRUE(origins.find(kOriginA) != origins.end()); 227 228 EXPECT_TRUE(GetOriginsForType(&client, kPerm).empty()); 229} 230 231TEST_F(IndexedDBQuotaClientTest, DeleteOrigin) { 232 IndexedDBQuotaClient client(idb_context()); 233 234 AddFakeIndexedDB(kOriginA, 1000); 235 AddFakeIndexedDB(kOriginB, 50); 236 EXPECT_EQ(1000, GetOriginUsage(&client, kOriginA, kTemp)); 237 EXPECT_EQ(50, GetOriginUsage(&client, kOriginB, kTemp)); 238 239 storage::QuotaStatusCode delete_status = DeleteOrigin(&client, kOriginA); 240 EXPECT_EQ(storage::kQuotaStatusOk, delete_status); 241 EXPECT_EQ(0, GetOriginUsage(&client, kOriginA, kTemp)); 242 EXPECT_EQ(50, GetOriginUsage(&client, kOriginB, kTemp)); 243} 244 245} // namespace content 246