1 // Copyright 2013 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 "chrome/browser/ui/app_list/search/common/dictionary_data_store.h" 6 7 #include "base/callback.h" 8 #include "base/json/json_file_value_serializer.h" 9 #include "base/json/json_string_value_serializer.h" 10 #include "base/logging.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "base/task_runner_util.h" 13 #include "base/threading/sequenced_worker_pool.h" 14 #include "base/values.h" 15 #include "content/public/browser/browser_thread.h" 16 17 using content::BrowserThread; 18 19 namespace app_list { 20 21 DictionaryDataStore::DictionaryDataStore(const base::FilePath& data_file) 22 : data_file_(data_file) { 23 std::string token("app-launcher-data-store"); 24 token.append(data_file.AsUTF8Unsafe()); 25 26 // Uses a SKIP_ON_SHUTDOWN file task runner because losing a couple 27 // associations is better than blocking shutdown. 28 base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool(); 29 file_task_runner_ = pool->GetSequencedTaskRunnerWithShutdownBehavior( 30 pool->GetNamedSequenceToken(token), 31 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 32 writer_.reset( 33 new base::ImportantFileWriter(data_file, file_task_runner_.get())); 34 35 cached_dict_.reset(new base::DictionaryValue); 36 } 37 38 DictionaryDataStore::~DictionaryDataStore() { 39 Flush(OnFlushedCallback()); 40 } 41 42 void DictionaryDataStore::Flush(const OnFlushedCallback& on_flushed) { 43 if (writer_->HasPendingWrite()) 44 writer_->DoScheduledWrite(); 45 46 if (on_flushed.is_null()) 47 return; 48 49 file_task_runner_->PostTaskAndReply( 50 FROM_HERE, base::Bind(&base::DoNothing), on_flushed); 51 } 52 53 void DictionaryDataStore::Load( 54 const DictionaryDataStore::OnLoadedCallback& on_loaded) { 55 base::PostTaskAndReplyWithResult( 56 file_task_runner_.get(), 57 FROM_HERE, 58 base::Bind(&DictionaryDataStore::LoadOnBlockingPool, this), 59 on_loaded); 60 } 61 62 void DictionaryDataStore::ScheduleWrite() { 63 writer_->ScheduleWrite(this); 64 } 65 66 scoped_ptr<base::DictionaryValue> DictionaryDataStore::LoadOnBlockingPool() { 67 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 68 69 int error_code = JSONFileValueSerializer::JSON_NO_ERROR; 70 std::string error_message; 71 JSONFileValueSerializer serializer(data_file_); 72 base::Value* value = serializer.Deserialize(&error_code, &error_message); 73 base::DictionaryValue* dict_value = NULL; 74 if (error_code != JSONFileValueSerializer::JSON_NO_ERROR || 75 !value || 76 !value->GetAsDictionary(&dict_value) || 77 !dict_value) { 78 return scoped_ptr<base::DictionaryValue>(); 79 } 80 81 base::DictionaryValue* return_dict = dict_value->DeepCopy(); 82 cached_dict_.reset(dict_value); 83 return make_scoped_ptr(return_dict).Pass(); 84 } 85 86 bool DictionaryDataStore::SerializeData(std::string* data) { 87 JSONStringValueSerializer serializer(data); 88 serializer.set_pretty_print(true); 89 return serializer.Serialize(*cached_dict_.get()); 90 } 91 92 } // namespace app_list 93