1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file.
4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/extensions/api/signed_in_devices/id_mapping_helper.h"
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/scoped_vector.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/rand_util.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/values.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/crx_file/id_util.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/sync_driver/device_info.h"
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using base::DictionaryValue;
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using base::Value;
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing sync_driver::DeviceInfo;
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace extensions {
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)std::string GetPublicIdFromGUID(
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const base::DictionaryValue& id_mapping,
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& guid) {
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (base::DictionaryValue::Iterator it(id_mapping);
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       !it.IsAtEnd();
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       it.Advance()) {
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::Value& value = it.value();
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    std::string guid_in_value;
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!value.GetAsString(&guid_in_value)) {
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      LOG(ERROR) << "Badly formatted dictionary";
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      continue;
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (guid_in_value == guid) {
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return it.key();
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return std::string();
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)std::string GetGUIDFromPublicId(
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const base::DictionaryValue& id_mapping,
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& id) {
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string guid;
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  id_mapping.GetString(id, &guid);
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return guid;
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Finds out a random unused id. First finds a random id.
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// If the id is in use, increments the id until it finds an unused id.
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)std::string GetRandomId(
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue& mapping,
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int device_count) {
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Set the max value for rand to be twice the device count.
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int max = device_count * 2;
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int rand_value = base::RandInt(0, max);
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string string_value;
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::Value *out_value;
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  do {
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    string_value = base::IntToString(rand_value);
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    rand_value++;
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } while (mapping.Get(string_value, &out_value));
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return string_value;
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void CreateMappingForUnmappedDevices(
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::vector<DeviceInfo*>* device_info,
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::DictionaryValue* value) {
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (unsigned int i = 0; i < device_info->size(); ++i) {
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DeviceInfo* device = (*device_info)[i];
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    std::string local_id = GetPublicIdFromGUID(*value,
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                               device->guid());
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // If the device does not have a local id, set one.
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (local_id.empty()) {
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      local_id = GetRandomId(*value, device_info->size());
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      value->SetString(local_id, device->guid());
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    device->set_public_id(local_id);
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)scoped_ptr<DeviceInfo> GetDeviceInfoForClientId(
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& client_id,
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& extension_id,
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Profile* profile) {
9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK(crx_file::id_util::IdIsValid(extension_id)) << extension_id
9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                                     << " is not valid";
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ScopedVector<DeviceInfo> devices = GetAllSignedInDevices(extension_id,
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                           profile);
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (ScopedVector<DeviceInfo>::iterator it = devices.begin();
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       it != devices.end();
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       ++it) {
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if ((*it)->guid() == client_id) {
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      scoped_ptr<DeviceInfo> device(*it);
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      devices.weak_erase(it);
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return device.Pass();
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return scoped_ptr<DeviceInfo>();
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace  extensions
108