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