signed_in_devices_api.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1// Copyright (c) 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/extensions/api/signed_in_devices/signed_in_devices_api.h"
6
7#include "base/memory/scoped_ptr.h"
8#include "base/memory/scoped_vector.h"
9#include "base/values.h"
10#include "chrome/browser/extensions/api/signed_in_devices/id_mapping_helper.h"
11#include "chrome/browser/extensions/extension_prefs.h"
12#include "chrome/browser/profiles/profile.h"
13#include "chrome/browser/sync/glue/device_info.h"
14#include "chrome/browser/sync/profile_sync_service.h"
15#include "chrome/browser/sync/profile_sync_service_factory.h"
16#include "chrome/common/extensions/api/signed_in_devices.h"
17
18using base::DictionaryValue;
19using browser_sync::DeviceInfo;
20
21namespace extensions {
22
23static const char kPrefStringForIdMapping[] = "id_mapping_dictioanry";
24
25// Gets the dictionary that stores the id mapping. The dictionary is stored
26// in the |ExtensionPrefs|.
27const base::DictionaryValue* GetIdMappingDictionary(
28    ExtensionPrefs* extension_prefs,
29    const std::string& extension_id) {
30  const base::DictionaryValue* out_value = NULL;
31  if (!extension_prefs->ReadPrefAsDictionary(
32          extension_id,
33          kPrefStringForIdMapping,
34          &out_value) || out_value == NULL) {
35    // Looks like this is the first call to get the dictionary. Let us create
36    // a dictionary and set it in to |extension_prefs|.
37    scoped_ptr<DictionaryValue> dictionary(new DictionaryValue());
38    out_value = dictionary.get();
39    extension_prefs->UpdateExtensionPref(
40        extension_id,
41        kPrefStringForIdMapping,
42        dictionary.release());
43  }
44
45  return out_value;
46}
47
48// Helper routine to get all signed in devices. The helper takes in
49// the pointers for |ProfileSyncService| and |Extensionprefs|. This
50// makes it easier to test by passing mock values for these pointers.
51ScopedVector<DeviceInfo> GetAllSignedInDevices(
52    const std::string& extension_id,
53    ProfileSyncService* pss,
54    ExtensionPrefs* extension_prefs) {
55  ScopedVector<DeviceInfo> devices = pss->GetAllSignedInDevices();
56  const DictionaryValue* mapping_dictionary = GetIdMappingDictionary(
57      extension_prefs,
58      extension_id);
59
60  CHECK(mapping_dictionary);
61
62  // |mapping_dictionary| is const. So make an editable copy.
63  scoped_ptr<DictionaryValue> editable_mapping_dictionary(
64      mapping_dictionary->DeepCopy());
65
66  CreateMappingForUnmappedDevices(&(devices.get()),
67                                  editable_mapping_dictionary.get());
68
69  // Write into |ExtensionPrefs| which will get persisted in disk.
70  extension_prefs->UpdateExtensionPref(extension_id,
71                                       kPrefStringForIdMapping,
72                                       editable_mapping_dictionary.release());
73  return devices.Pass();
74}
75
76ScopedVector<DeviceInfo> GetAllSignedInDevices(
77    const std::string& extension_id,
78    Profile* profile) {
79  // Get the profile sync service and extension prefs pointers
80  // and call the helper.
81  ProfileSyncService* pss = ProfileSyncServiceFactory::GetForProfile(profile);
82  ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile);
83
84  return GetAllSignedInDevices(extension_id,
85                               pss,
86                               extension_prefs);
87}
88
89scoped_ptr<DeviceInfo> GetLocalDeviceInfo(const std::string& extension_id,
90                                          Profile* profile) {
91  ProfileSyncService* pss = ProfileSyncServiceFactory::GetForProfile(profile);
92  if (!pss) {
93    return scoped_ptr<DeviceInfo>();
94  }
95  std::string guid = pss->GetLocalDeviceGUID();
96  scoped_ptr<DeviceInfo> device = GetDeviceInfoForClientId(guid,
97                                                           extension_id,
98                                                           profile);
99  return device.Pass();
100}
101
102bool SignedInDevicesGetFunction::RunImpl() {
103  scoped_ptr<api::signed_in_devices::Get::Params> params(
104      api::signed_in_devices::Get::Params::Create(*args_));
105  EXTENSION_FUNCTION_VALIDATE(params.get());
106
107  bool is_local = params->is_local.get() ? *params->is_local : false;
108
109  if (is_local) {
110    scoped_ptr<DeviceInfo> device = GetLocalDeviceInfo(extension_id(),
111                                                       profile());
112    base::ListValue* result = new base::ListValue();
113    if (device.get()) {
114      result->Append(device->ToValue());
115    }
116    SetResult(result);
117    return true;
118  }
119
120  ScopedVector<DeviceInfo> devices = GetAllSignedInDevices(extension_id(),
121                                                           profile());
122
123  scoped_ptr<base::ListValue> result(new base::ListValue());
124
125  for (ScopedVector<DeviceInfo>::const_iterator it = devices.begin();
126       it != devices.end();
127       ++it) {
128    result->Append((*it)->ToValue());
129  }
130
131  SetResult(result.release());
132  return true;
133}
134
135}  // namespace extensions
136
137