1 // Copyright 2014 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.
6 #include "base/files/file_util.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "content/public/browser/browser_context.h"
12 #include "content/public/test/test_browser_context.h"
13 #include "content/public/test/test_browser_thread.h"
14 #include "extensions/browser/api/extensions_api_client.h"
15 #include "extensions/browser/api/storage/leveldb_settings_storage_factory.h"
16 #include "extensions/browser/api/storage/settings_namespace.h"
17 #include "extensions/browser/api/storage/settings_test_util.h"
18 #include "extensions/browser/api/storage/storage_frontend.h"
19 #include "extensions/browser/extensions_test.h"
20 #include "extensions/browser/value_store/value_store.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 using content::BrowserThread
;
25 namespace extensions
{
27 namespace settings
= settings_namespace
;
28 namespace util
= settings_test_util
;
32 // To save typing ValueStore::DEFAULTS everywhere.
33 const ValueStore::WriteOptions DEFAULTS
= ValueStore::DEFAULTS
;
37 // A better name for this would be StorageFrontendTest, but the historical name
38 // has been ExtensionSettingsFrontendTest. In order to preserve crash/failure
39 // history, the test names are unchanged.
40 class ExtensionSettingsFrontendTest
: public ExtensionsTest
{
42 ExtensionSettingsFrontendTest()
43 : storage_factory_(new util::ScopedSettingsStorageFactory()),
44 ui_thread_(BrowserThread::UI
, base::MessageLoop::current()),
45 file_thread_(BrowserThread::FILE, base::MessageLoop::current()) {}
47 void SetUp() override
{
48 ExtensionsTest::SetUp();
49 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
53 void TearDown() override
{
55 // Execute any pending deletion tasks.
56 message_loop_
.RunUntilIdle();
57 ExtensionsTest::TearDown();
61 void ResetFrontend() {
62 storage_factory_
->Reset(new LeveldbSettingsStorageFactory());
63 frontend_
= StorageFrontend::CreateForTesting(storage_factory_
,
64 browser_context()).Pass();
67 base::ScopedTempDir temp_dir_
;
68 scoped_ptr
<StorageFrontend
> frontend_
;
69 scoped_refptr
<util::ScopedSettingsStorageFactory
> storage_factory_
;
72 base::MessageLoop message_loop_
;
73 content::TestBrowserThread ui_thread_
;
74 content::TestBrowserThread file_thread_
;
75 ExtensionsAPIClient extensions_api_client_
;
78 // Get a semblance of coverage for both extension and app settings by
79 // alternating in each test.
80 // TODO(kalman): explicitly test the two interact correctly.
82 // Tests that the frontend is set up correctly.
83 TEST_F(ExtensionSettingsFrontendTest
, Basics
) {
84 // Local storage is always enabled.
85 EXPECT_TRUE(frontend_
->IsStorageEnabled(settings::LOCAL
));
86 EXPECT_TRUE(frontend_
->GetValueStoreCache(settings::LOCAL
));
88 // Invalid storage areas are not available.
89 EXPECT_FALSE(frontend_
->IsStorageEnabled(settings::INVALID
));
90 EXPECT_FALSE(frontend_
->GetValueStoreCache(settings::INVALID
));
93 TEST_F(ExtensionSettingsFrontendTest
, SettingsPreservedAcrossReconstruction
) {
94 const std::string id
= "ext";
95 scoped_refptr
<const Extension
> extension
=
96 util::AddExtensionWithId(browser_context(), id
, Manifest::TYPE_EXTENSION
);
99 util::GetStorage(extension
, settings::LOCAL
, frontend_
.get());
101 // The correctness of Get/Set/Remove/Clear is tested elsewhere so no need to
104 base::StringValue
bar("bar");
105 ValueStore::WriteResult result
= storage
->Set(DEFAULTS
, "foo", bar
);
106 ASSERT_FALSE(result
->HasError());
110 ValueStore::ReadResult result
= storage
->Get();
111 ASSERT_FALSE(result
->HasError());
112 EXPECT_FALSE(result
->settings().empty());
116 storage
= util::GetStorage(extension
, settings::LOCAL
, frontend_
.get());
119 ValueStore::ReadResult result
= storage
->Get();
120 ASSERT_FALSE(result
->HasError());
121 EXPECT_FALSE(result
->settings().empty());
125 TEST_F(ExtensionSettingsFrontendTest
, SettingsClearedOnUninstall
) {
126 const std::string id
= "ext";
127 scoped_refptr
<const Extension
> extension
= util::AddExtensionWithId(
128 browser_context(), id
, Manifest::TYPE_LEGACY_PACKAGED_APP
);
130 ValueStore
* storage
=
131 util::GetStorage(extension
, settings::LOCAL
, frontend_
.get());
134 base::StringValue
bar("bar");
135 ValueStore::WriteResult result
= storage
->Set(DEFAULTS
, "foo", bar
);
136 ASSERT_FALSE(result
->HasError());
139 // This would be triggered by extension uninstall via a DataDeleter.
140 frontend_
->DeleteStorageSoon(id
);
141 base::MessageLoop::current()->RunUntilIdle();
143 // The storage area may no longer be valid post-uninstall, so re-request.
144 storage
= util::GetStorage(extension
, settings::LOCAL
, frontend_
.get());
146 ValueStore::ReadResult result
= storage
->Get();
147 ASSERT_FALSE(result
->HasError());
148 EXPECT_TRUE(result
->settings().empty());
152 TEST_F(ExtensionSettingsFrontendTest
, LeveldbDatabaseDeletedFromDiskOnClear
) {
153 const std::string id
= "ext";
154 scoped_refptr
<const Extension
> extension
=
155 util::AddExtensionWithId(browser_context(), id
, Manifest::TYPE_EXTENSION
);
157 ValueStore
* storage
=
158 util::GetStorage(extension
, settings::LOCAL
, frontend_
.get());
161 base::StringValue
bar("bar");
162 ValueStore::WriteResult result
= storage
->Set(DEFAULTS
, "foo", bar
);
163 ASSERT_FALSE(result
->HasError());
164 EXPECT_TRUE(base::PathExists(temp_dir_
.path()));
167 // Should need to both clear the database and delete the frontend for the
168 // leveldb database to be deleted from disk.
170 ValueStore::WriteResult result
= storage
->Clear();
171 ASSERT_FALSE(result
->HasError());
172 EXPECT_TRUE(base::PathExists(temp_dir_
.path()));
176 base::MessageLoop::current()->RunUntilIdle();
177 // TODO(kalman): Figure out why this fails, despite appearing to work.
178 // Leaving this commented out rather than disabling the whole test so that the
179 // deletion code paths are at least exercised.
180 //EXPECT_FALSE(base::PathExists(temp_dir_.path()));
183 // Disabled (slow), http://crbug.com/322751 .
184 TEST_F(ExtensionSettingsFrontendTest
,
185 DISABLED_QuotaLimitsEnforcedCorrectlyForSyncAndLocal
) {
186 const std::string id
= "ext";
187 scoped_refptr
<const Extension
> extension
=
188 util::AddExtensionWithId(browser_context(), id
, Manifest::TYPE_EXTENSION
);
190 ValueStore
* sync_storage
=
191 util::GetStorage(extension
, settings::SYNC
, frontend_
.get());
192 ValueStore
* local_storage
=
193 util::GetStorage(extension
, settings::LOCAL
, frontend_
.get());
195 // Sync storage should run out after ~100K.
196 scoped_ptr
<base::Value
> kilobyte
= util::CreateKilobyte();
197 for (int i
= 0; i
< 100; ++i
) {
198 sync_storage
->Set(DEFAULTS
, base::IntToString(i
), *kilobyte
);
201 EXPECT_TRUE(sync_storage
->Set(DEFAULTS
, "WillError", *kilobyte
)->HasError());
203 // Local storage shouldn't run out after ~100K.
204 for (int i
= 0; i
< 100; ++i
) {
205 local_storage
->Set(DEFAULTS
, base::IntToString(i
), *kilobyte
);
209 local_storage
->Set(DEFAULTS
, "WontError", *kilobyte
)->HasError());
211 // Local storage should run out after ~5MB.
212 scoped_ptr
<base::Value
> megabyte
= util::CreateMegabyte();
213 for (int i
= 0; i
< 5; ++i
) {
214 local_storage
->Set(DEFAULTS
, base::IntToString(i
), *megabyte
);
217 EXPECT_TRUE(local_storage
->Set(DEFAULTS
, "WillError", *megabyte
)->HasError());
220 } // namespace extensions