1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/value_store/value_store_frontend.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/debug/trace_event.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/value_store/leveldb_value_store.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ValueStoreFrontend::Backend : public base::RefCountedThreadSafe<Backend> { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Backend() : storage_(NULL) {} 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Init(const base::FilePath& db_path) { 21effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!storage_); 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TRACE_EVENT0("ValueStoreFrontend::Backend", "Init"); 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db_path_ = db_path; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) storage_ = new LeveldbValueStore(db_path); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This variant is useful for testing (using a mock ValueStore). 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void InitWithStore(scoped_ptr<ValueStore> storage) { 30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!storage_); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage_ = storage.release(); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Get(const std::string& key, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ValueStoreFrontend::ReadCallback& callback) { 37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ValueStore::ReadResult result = storage_->Get(key); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Extract the value from the ReadResult and pass ownership of it to the 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // callback. 423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch scoped_ptr<base::Value> value; 433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (!result->HasError()) { 4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) result->settings().RemoveWithoutPathExpansion(key, &value); 453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } else { 4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) LOG(WARNING) << "Reading " << key << " from " << db_path_.value() 4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << " failed: " << result->error().message; 483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ValueStoreFrontend::Backend::RunCallback, 523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch this, callback, base::Passed(&value))); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Set(const std::string& key, scoped_ptr<base::Value> value) { 56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't need the old value, so skip generating changes. 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ValueStore::WriteResult result = storage_->Set( 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ValueStore::IGNORE_QUOTA | ValueStore::NO_GENERATE_CHANGES, 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) key, 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *value.get()); 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG_IF(ERROR, result->HasError()) << "Error while writing " << key << " to " 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) << db_path_.value(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Remove(const std::string& key) { 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::FILE); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) storage_->Remove(key); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCountedThreadSafe<Backend>; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Backend() { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete storage_; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, storage_); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RunCallback(const ValueStoreFrontend::ReadCallback& callback, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Value> value) { 84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_CURRENTLY_ON(BrowserThread::UI); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(value.Pass()); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The actual ValueStore that handles persisting the data to disk. Used 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // exclusively on the FILE thread. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ValueStore* storage_; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath db_path_; 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Backend); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ValueStoreFrontend::ValueStoreFrontend() 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : backend_(new Backend()) { 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ValueStoreFrontend::ValueStoreFrontend(const base::FilePath& db_path) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : backend_(new Backend()) { 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Init(db_path); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ValueStoreFrontend::ValueStoreFrontend(scoped_ptr<ValueStore> value_store) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : backend_(new Backend()) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ValueStoreFrontend::Backend::InitWithStore, 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) backend_, base::Passed(&value_store))); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ValueStoreFrontend::~ValueStoreFrontend() { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ValueStoreFrontend::Init(const base::FilePath& db_path) { 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ValueStoreFrontend::Backend::Init, 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) backend_, db_path)); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ValueStoreFrontend::Get(const std::string& key, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ReadCallback& callback) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ValueStoreFrontend::Backend::Get, 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_, key, callback)); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ValueStoreFrontend::Set(const std::string& key, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Value> value) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ValueStoreFrontend::Backend::Set, 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) backend_, key, base::Passed(&value))); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ValueStoreFrontend::Remove(const std::string& key) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ValueStoreFrontend::Backend::Remove, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_, key)); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 148