1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file. 4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/command_line.h" 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/file_path.h" 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/memory/ref_counted.h" 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/stringprintf.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/test/test_browser_context.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/extensions_api_client.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/api/storage/leveldb_settings_storage_factory.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/api/storage/settings_storage_quota_enforcer.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/api/storage/settings_test_util.h" 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/api/storage/storage_api.h" 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/api/storage/storage_frontend.h" 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api_unittest.h" 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/event_router.h" 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/extension_prefs.h" 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/extension_system.h" 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/mock_extension_system.h" 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/test_extensions_browser_client.h" 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/value_store/leveldb_value_store.h" 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/value_store/value_store.h" 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/common/manifest.h" 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/common/test_util.h" 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/db.h" 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace extensions { 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace { 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Caller owns the returned object. 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)KeyedService* CreateStorageFrontendForTesting( 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) content::BrowserContext* context) { 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return StorageFrontend::CreateForTesting(new LeveldbSettingsStorageFactory(), 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) context); 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass StorageApiUnittest : public ApiUnitTest { 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public: 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci StorageApiUnittest() {} 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void SetUp() OVERRIDE { 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ApiUnitTest::SetUp(); 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions_browser_client()->set_extension_system_factory( 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &extension_system_factory_); 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) protected: 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Runs the storage.set() API function with local storage. 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void RunSetFunction(const std::string& key, const std::string& value) { 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunFunction( 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new StorageStorageAreaSetFunction(), 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::StringPrintf( 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "[\"local\", {\"%s\": \"%s\"}]", key.c_str(), value.c_str())); 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Runs the storage.get() API function with the local storage, and populates 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // |value| with the string result. 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) testing::AssertionResult RunGetFunction(const std::string& key, 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string* value) { 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<base::Value> result = RunFunctionAndReturnValue( 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new StorageStorageAreaGetFunction(), 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::StringPrintf("[\"local\", \"%s\"]", key.c_str())); 685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!result.get()) 695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return testing::AssertionFailure() << "No result"; 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::DictionaryValue* dict = NULL; 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!result->GetAsDictionary(&dict)) 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return testing::AssertionFailure() << result << " was not a dictionary."; 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!dict->GetString(key, value)) { 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return testing::AssertionFailure() << " could not retrieve a string from" 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << dict << " at " << key; 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return testing::AssertionSuccess(); 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MockExtensionSystemFactory< 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci settings_test_util::MockExtensionSystemWithEventRouter> 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_system_factory_; 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ExtensionsAPIClient extensions_api_client_; 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}; 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(StorageApiUnittest, RestoreCorruptedStorage) { 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Ensure a StorageFrontend can be created on demand. The StorageFrontend 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // will be owned by the KeyedService system. 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StorageFrontend::GetFactoryInstance()->SetTestingFactory( 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci browser_context(), &CreateStorageFrontendForTesting); 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const char kKey[] = "key"; 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const char kValue[] = "value"; 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string result; 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Do a simple set/get combo to make sure the API works. 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunSetFunction(kKey, kValue); 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(RunGetFunction(kKey, &result)); 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(kValue, result); 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Corrupt the store. This is not as pretty as ideal, because we use knowledge 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // of the underlying structure, but there's no real good way to corrupt a 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // store other than directly modifying the files. 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ValueStore* store = 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) settings_test_util::GetStorage(extension_ref(), 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) settings_namespace::LOCAL, 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci StorageFrontend::Get(browser_context())); 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ASSERT_TRUE(store); 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SettingsStorageQuotaEnforcer* quota_store = 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static_cast<SettingsStorageQuotaEnforcer*>(store); 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LeveldbValueStore* leveldb_store = 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static_cast<LeveldbValueStore*>(quota_store->get_delegate_for_test()); 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) leveldb::WriteBatch batch; 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) batch.Put(kKey, "[{(.*+\"\'\\"); 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(leveldb_store->WriteToDbForTest(&batch)); 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(leveldb_store->Get(kKey)->IsCorrupted()); 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Running another set should end up working (even though it will restore the 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // store behind the scenes). 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RunSetFunction(kKey, kValue); 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(RunGetFunction(kKey, &result)); 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(kValue, result); 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace extensions 126