190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/app_list/search/history_data_store.h" 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/callback.h" 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/json/json_file_value_serializer.h" 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/json/json_string_value_serializer.h" 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h" 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/task_runner_util.h" 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h" 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/values.h" 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using content::BrowserThread; 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace app_list { 2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace { 2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kKeyVersion[] = "version"; 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kCurrentVersion[] = "1"; 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kKeyAssociations[] = "associations"; 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kKeyPrimary[] = "p"; 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kKeySecondary[] = "s"; 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kKeyUpdateTime[] = "t"; 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Extracts strings from ListValue. 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void GetSecondary(const base::ListValue* list, 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) HistoryData::SecondaryDeque* secondary) { 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) HistoryData::SecondaryDeque results; 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (base::ListValue::const_iterator it = list->begin(); 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) it != list->end(); ++it) { 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string str; 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!(*it)->GetAsString(&str)) 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) results.push_back(str); 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) secondary->swap(results); 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// V1 format json dictionary: 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// { 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// "version": "1", 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// "associations": { 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// "user typed query": { 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// "p" : "result id of primary association", 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// "s" : [ 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// "result id of 1st (oldest) secondary association", 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// ... 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// "result id of the newest secondary association" 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// ], 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// "t" : "last_update_timestamp" 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// }, 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// ... 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// } 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// } 638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)scoped_ptr<HistoryData::Associations> Parse( 648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) scoped_ptr<base::DictionaryValue> dict) { 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string version; 668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!dict->GetStringWithoutPathExpansion(kKeyVersion, &version) || 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) version != kCurrentVersion) { 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return scoped_ptr<HistoryData::Associations>(); 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const base::DictionaryValue* assoc_dict = NULL; 728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!dict->GetDictionaryWithoutPathExpansion(kKeyAssociations, 738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) &assoc_dict) || 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) !assoc_dict) { 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return scoped_ptr<HistoryData::Associations>(); 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<HistoryData::Associations> data(new HistoryData::Associations); 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (base::DictionaryValue::Iterator it(*assoc_dict); 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) !it.IsAtEnd(); it.Advance()) { 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const base::DictionaryValue* entry_dict = NULL; 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!it.value().GetAsDictionary(&entry_dict)) 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string primary; 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string update_time_string; 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!entry_dict->GetStringWithoutPathExpansion(kKeyPrimary, &primary) || 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) !entry_dict->GetStringWithoutPathExpansion(kKeyUpdateTime, 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &update_time_string)) { 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const base::ListValue* secondary_list = NULL; 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) HistoryData::SecondaryDeque secondary; 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (entry_dict->GetListWithoutPathExpansion(kKeySecondary, &secondary_list)) 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GetSecondary(secondary_list, &secondary); 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& query = it.key(); 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) HistoryData::Data& association_data = (*data.get())[query]; 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) association_data.primary = primary; 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) association_data.secondary.swap(secondary); 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int64 update_time_val; 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::StringToInt64(update_time_string, &update_time_val); 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) association_data.update_time = 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Time::FromInternalValue(update_time_val); 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return data.Pass(); 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)HistoryDataStore::HistoryDataStore(const base::FilePath& data_file) 1158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : data_store_(new DictionaryDataStore(data_file)) { 1168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::DictionaryValue* dict = data_store_->cached_dict(); 1178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK(dict); 1188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) dict->SetString(kKeyVersion, kCurrentVersion); 1198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) dict->Set(kKeyAssociations, new base::DictionaryValue); 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)HistoryDataStore::~HistoryDataStore() { 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void HistoryDataStore::Flush( 1268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const DictionaryDataStore::OnFlushedCallback& on_flushed) { 1278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) data_store_->Flush(on_flushed); 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void HistoryDataStore::Load( 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const HistoryDataStore::OnLoadedCallback& on_loaded) { 1328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) data_store_->Load(base::Bind(&HistoryDataStore::OnDictionaryLoadedCallback, 1338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) this, 1348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) on_loaded)); 13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void HistoryDataStore::SetPrimary(const std::string& query, 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& result) { 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::DictionaryValue* entry_dict = GetEntryDict(query); 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) entry_dict->SetWithoutPathExpansion(kKeyPrimary, 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) new base::StringValue(result)); 1428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) data_store_->ScheduleWrite(); 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void HistoryDataStore::SetSecondary( 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& query, 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const HistoryData::SecondaryDeque& results) { 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<base::ListValue> results_list(new base::ListValue); 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (size_t i = 0; i< results.size(); ++i) 15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) results_list->AppendString(results[i]); 15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::DictionaryValue* entry_dict = GetEntryDict(query); 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) entry_dict->SetWithoutPathExpansion(kKeySecondary, results_list.release()); 1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) data_store_->ScheduleWrite(); 15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void HistoryDataStore::SetUpdateTime(const std::string& query, 15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const base::Time& update_time) { 15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::DictionaryValue* entry_dict = GetEntryDict(query); 16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) entry_dict->SetWithoutPathExpansion(kKeyUpdateTime, 16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) new base::StringValue(base::Int64ToString( 16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) update_time.ToInternalValue()))); 1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) data_store_->ScheduleWrite(); 16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void HistoryDataStore::Delete(const std::string& query) { 16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::DictionaryValue* assoc_dict = GetAssociationDict(); 16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) assoc_dict->RemoveWithoutPathExpansion(query, NULL); 1698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) data_store_->ScheduleWrite(); 17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)base::DictionaryValue* HistoryDataStore::GetAssociationDict() { 1738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::DictionaryValue* cached_dict = data_store_->cached_dict(); 1748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DCHECK(cached_dict); 1758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::DictionaryValue* assoc_dict = NULL; 1778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CHECK(cached_dict->GetDictionary(kKeyAssociations, &assoc_dict) && 17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) assoc_dict); 17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return assoc_dict; 18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)base::DictionaryValue* HistoryDataStore::GetEntryDict( 18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& query) { 18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::DictionaryValue* assoc_dict = GetAssociationDict(); 18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::DictionaryValue* entry_dict = NULL; 18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!assoc_dict->GetDictionaryWithoutPathExpansion(query, &entry_dict)) { 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Creates one if none exists. Ownership is taken in the set call after. 19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) entry_dict = new base::DictionaryValue; 19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) assoc_dict->SetWithoutPathExpansion(query, entry_dict); 19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return entry_dict; 19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void HistoryDataStore::OnDictionaryLoadedCallback( 1988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) OnLoadedCallback callback, scoped_ptr<base::DictionaryValue> dict) { 1998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!dict) { 2008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) callback.Run(scoped_ptr<HistoryData::Associations>()); 2018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } else { 2028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) callback.Run(Parse(dict.Pass()).Pass()); 20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace app_list 207