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/id_mapping_helper.h" 6 7 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_vector.h" 9 #include "base/rand_util.h" 10 #include "base/strings/string_number_conversions.h" 11 #include "base/values.h" 12 #include "chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h" 13 #include "chrome/browser/profiles/profile.h" 14 #include "components/crx_file/id_util.h" 15 #include "components/sync_driver/device_info.h" 16 17 using base::DictionaryValue; 18 using base::Value; 19 using sync_driver::DeviceInfo; 20 21 namespace extensions { 22 23 std::string GetPublicIdFromGUID( 24 const base::DictionaryValue& id_mapping, 25 const std::string& guid) { 26 for (base::DictionaryValue::Iterator it(id_mapping); 27 !it.IsAtEnd(); 28 it.Advance()) { 29 const base::Value& value = it.value(); 30 std::string guid_in_value; 31 if (!value.GetAsString(&guid_in_value)) { 32 LOG(ERROR) << "Badly formatted dictionary"; 33 continue; 34 } 35 if (guid_in_value == guid) { 36 return it.key(); 37 } 38 } 39 40 return std::string(); 41 } 42 43 std::string GetGUIDFromPublicId( 44 const base::DictionaryValue& id_mapping, 45 const std::string& id) { 46 std::string guid; 47 id_mapping.GetString(id, &guid); 48 return guid; 49 } 50 51 // Finds out a random unused id. First finds a random id. 52 // If the id is in use, increments the id until it finds an unused id. 53 std::string GetRandomId( 54 const base::DictionaryValue& mapping, 55 int device_count) { 56 // Set the max value for rand to be twice the device count. 57 int max = device_count * 2; 58 int rand_value = base::RandInt(0, max); 59 std::string string_value; 60 const base::Value *out_value; 61 62 do { 63 string_value = base::IntToString(rand_value); 64 rand_value++; 65 } while (mapping.Get(string_value, &out_value)); 66 67 return string_value; 68 } 69 70 void CreateMappingForUnmappedDevices( 71 std::vector<DeviceInfo*>* device_info, 72 base::DictionaryValue* value) { 73 for (unsigned int i = 0; i < device_info->size(); ++i) { 74 DeviceInfo* device = (*device_info)[i]; 75 std::string local_id = GetPublicIdFromGUID(*value, 76 device->guid()); 77 78 // If the device does not have a local id, set one. 79 if (local_id.empty()) { 80 local_id = GetRandomId(*value, device_info->size()); 81 value->SetString(local_id, device->guid()); 82 } 83 device->set_public_id(local_id); 84 } 85 } 86 87 scoped_ptr<DeviceInfo> GetDeviceInfoForClientId( 88 const std::string& client_id, 89 const std::string& extension_id, 90 Profile* profile) { 91 DCHECK(crx_file::id_util::IdIsValid(extension_id)) << extension_id 92 << " is not valid"; 93 ScopedVector<DeviceInfo> devices = GetAllSignedInDevices(extension_id, 94 profile); 95 for (ScopedVector<DeviceInfo>::iterator it = devices.begin(); 96 it != devices.end(); 97 ++it) { 98 if ((*it)->guid() == client_id) { 99 scoped_ptr<DeviceInfo> device(*it); 100 devices.weak_erase(it); 101 return device.Pass(); 102 } 103 } 104 return scoped_ptr<DeviceInfo>(); 105 } 106 107 } // namespace extensions 108