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