1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2012 The Android Open Source Project 3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License"); 5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License. 6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at 7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// http://www.apache.org/licenses/LICENSE-2.0 9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software 11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS, 12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and 14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License. 15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 1652cd19bfd52226611d924930f1178307f79d5fdcChris Masone 1752cd19bfd52226611d924930f1178307f79d5fdcChris Masone#include "shill/profile.h" 1852cd19bfd52226611d924930f1178307f79d5fdcChris Masone 196515aabcd1fbbb9ff2090c9675c17eeef64e7474Chris Masone#include <set> 2052cd19bfd52226611d924930f1178307f79d5fdcChris Masone#include <string> 216791a43add38926966bd420e89541717fb2cb2b5Chris Masone#include <vector> 2252cd19bfd52226611d924930f1178307f79d5fdcChris Masone 2311c213f3cf64f27a0e42ee6da95e98bd1d4b3202Ben Chan#include <base/files/file_util.h> 243e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood#include <base/stl_util.h> 25a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_split.h> 26a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_util.h> 27a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/stringprintf.h> 28289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#if defined(__ANDROID__) 29289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#include <dbus/service_constants.h> 30289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#else 3188cbd5f509862f746abbfe99df0605dcc0de40b0Chris Masone#include <chromeos/dbus/service_constants.h> 32289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#endif // __ANDROID__ 3352cd19bfd52226611d924930f1178307f79d5fdcChris Masone 3452cd19bfd52226611d924930f1178307f79d5fdcChris Masone#include "shill/adaptor_interfaces.h" 3552cd19bfd52226611d924930f1178307f79d5fdcChris Masone#include "shill/control_interface.h" 36b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley#include "shill/logging.h" 376791a43add38926966bd420e89541717fb2cb2b5Chris Masone#include "shill/manager.h" 3852cd19bfd52226611d924930f1178307f79d5fdcChris Masone#include "shill/property_accessor.h" 397aa5f90848b530999d8b6788ecb40aa30871c7aeChris Masone#include "shill/service.h" 4004147470fdeaaf9ab7588bd3a7988d74aa990068mukesh agrawal#include "shill/store_factory.h" 419d779936d8f8c2d74b30883e2a2622c4207fe797Chris Masone#include "shill/store_interface.h" 4292496a43b023b912f7f251d0167be360b3335690mukesh agrawal#include "shill/stub_storage.h" 4352cd19bfd52226611d924930f1178307f79d5fdcChris Masone 440e1cdeae24dd678a5fe27c840802582c0ca45ec0Albert Chaulkusing base::FilePath; 456515aabcd1fbbb9ff2090c9675c17eeef64e7474Chris Masoneusing std::set; 4652cd19bfd52226611d924930f1178307f79d5fdcChris Masoneusing std::string; 476791a43add38926966bd420e89541717fb2cb2b5Chris Masoneusing std::vector; 4852cd19bfd52226611d924930f1178307f79d5fdcChris Masone 4952cd19bfd52226611d924930f1178307f79d5fdcChris Masonenamespace shill { 50a4766822880815bafdc69778ccaccaf661536181Darin Petkov 51e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal#if defined(ENABLE_JSON_STORE) 52e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawalnamespace { 53e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawalconst char kFileExtensionJson[] = "json"; 54e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal} 55e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal#endif 56e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal 5778af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart// static 5878af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewartconst char Profile::kUserProfileListPathname[] = 5978af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart RUNDIR "/loaded_profile_list"; 6078af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart 611a212a6b98b22ad1d69652bb26a9e94138635476Paul StewartProfile::Profile(ControlInterface* control_interface, 621a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart Metrics* metrics, 631a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart Manager* manager, 641a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart const Identifier& name, 65e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal const base::FilePath& storage_directory, 667df0c672458bee8f4ff33004103351d59a9f4b50Chris Masone bool connect_to_rpc) 675133b71eaa00535739ebbddd8a8f31cd8fcf33a8Thieu Le : metrics_(metrics), 685133b71eaa00535739ebbddd8a8f31cd8fcf33a8Thieu Le manager_(manager), 69a92b0a0438803ebb3432d7b42672fbb7fb6bccf4Peter Qiu control_interface_(control_interface), 7044b9934a9528c0c19c82e0c6a79642eefeb54ea2mukesh agrawal name_(name) { 717df0c672458bee8f4ff33004103351d59a9f4b50Chris Masone if (connect_to_rpc) 727df0c672458bee8f4ff33004103351d59a9f4b50Chris Masone adaptor_.reset(control_interface->CreateProfileAdaptor(this)); 737df0c672458bee8f4ff33004103351d59a9f4b50Chris Masone 745dc58814ae6b1a40f77255986188e43817361ae0Ben Chan // kCheckPortalListProperty: Registered in DefaultProfile 755dc58814ae6b1a40f77255986188e43817361ae0Ben Chan // kCountryProperty: Registered in DefaultProfile 765dc58814ae6b1a40f77255986188e43817361ae0Ben Chan store_.RegisterConstString(kNameProperty, &name_.identifier); 77f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart store_.RegisterConstString(kUserHashProperty, &name_.user_hash); 7888cbd5f509862f746abbfe99df0605dcc0de40b0Chris Masone 795dc58814ae6b1a40f77255986188e43817361ae0Ben Chan // kOfflineModeProperty: Registered in DefaultProfile 805dc58814ae6b1a40f77255986188e43817361ae0Ben Chan // kPortalURLProperty: Registered in DefaultProfile 8188cbd5f509862f746abbfe99df0605dcc0de40b0Chris Masone 825dc58814ae6b1a40f77255986188e43817361ae0Ben Chan HelpRegisterConstDerivedStrings(kServicesProperty, 83bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal &Profile::EnumerateAvailableServices); 845dc58814ae6b1a40f77255986188e43817361ae0Ben Chan HelpRegisterConstDerivedStrings(kEntriesProperty, &Profile::EnumerateEntries); 85e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal 86e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal if (name.user.empty()) { 87e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // Subtle: Profile is only directly instantiated for user 88e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // profiles. And user profiles must have a non-empty 89e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // |name.user|. So we want to CHECK here. But Profile is also the 90e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // base class for DefaultProfile. So a CHECK here would cause us 91e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // to abort whenever we attempt to instantiate a DefaultProfile. 92e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // 93e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // Instead, we leave |persistent_profile_path_| unintialized. One 94e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // of two things will happen: a) we become a DefaultProfile, and 95e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // the DefaultProfile ctor sets |persistent_profile_path_|, or b) 96e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // we really are destined to be a user Profile. In the latter 97e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // case, our |name| argument was invalid, 98e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // |persistent_profile_path_| is never set, and we CHECK for an 99e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // empty |persistent_profile_path_| in InitStorage(). 100e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // 101e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // TODO(quiche): Clean this up. crbug.com/527553 102e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal } else { 103e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal persistent_profile_path_ = GetFinalStoragePath(storage_directory, name); 104e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal } 10552cd19bfd52226611d924930f1178307f79d5fdcChris Masone} 10652cd19bfd52226611d924930f1178307f79d5fdcChris Masone 1076515aabcd1fbbb9ff2090c9675c17eeef64e7474Chris MasoneProfile::~Profile() {} 10852cd19bfd52226611d924930f1178307f79d5fdcChris Masone 109c80c460b90378124cc945b0b1f619d86949000a7mukesh agrawalbool Profile::InitStorage(InitStorageOption storage_option, Error* error) { 110e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal CHECK(!persistent_profile_path_.empty()); 11104147470fdeaaf9ab7588bd3a7988d74aa990068mukesh agrawal std::unique_ptr<StoreInterface> storage( 112e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal StoreFactory::GetInstance()->CreateStore(persistent_profile_path_)); 1135dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart bool already_exists = storage->IsNonEmpty(); 1145dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart if (!already_exists && storage_option != kCreateNew && 1155dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart storage_option != kCreateOrOpenExisting) { 11634f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart Error::PopulateAndLog( 11734f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart FROM_HERE, error, Error::kNotFound, 1185dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart base::StringPrintf("Profile storage for %s:%s does not already exist", 119be005174bce39ddad185c2eb6808117484d522adPaul Stewart name_.user.c_str(), name_.identifier.c_str())); 1205dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart return false; 1215dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart } else if (already_exists && storage_option != kOpenExisting && 1225dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart storage_option != kCreateOrOpenExisting) { 12334f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart Error::PopulateAndLog( 12434f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart FROM_HERE, error, Error::kAlreadyExists, 1255dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart base::StringPrintf("Profile storage for %s:%s already exists", 126be005174bce39ddad185c2eb6808117484d522adPaul Stewart name_.user.c_str(), name_.identifier.c_str())); 1275dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart return false; 1285dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart } 129b9c00597eb1f6d2560f7e88cb0d1f627228840d4Chris Masone if (!storage->Open()) { 13034f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart Error::PopulateAndLog( 13134f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart FROM_HERE, error, Error::kInternalError, 132b9c00597eb1f6d2560f7e88cb0d1f627228840d4Chris Masone base::StringPrintf("Could not open profile storage for %s:%s", 133be005174bce39ddad185c2eb6808117484d522adPaul Stewart name_.user.c_str(), name_.identifier.c_str())); 1342ebc16da6068c8c61658b39cf70d157d7d0911ebPaul Stewart if (already_exists) { 13592496a43b023b912f7f251d0167be360b3335690mukesh agrawal // The profile contents are corrupt, or we do not have access to 1362ebc16da6068c8c61658b39cf70d157d7d0911ebPaul Stewart // this file. Move this file out of the way so a future open attempt 1372ebc16da6068c8c61658b39cf70d157d7d0911ebPaul Stewart // will succeed, assuming the failure reason was the former. 1382ebc16da6068c8c61658b39cf70d157d7d0911ebPaul Stewart storage->MarkAsCorrupted(); 1395133b71eaa00535739ebbddd8a8f31cd8fcf33a8Thieu Le metrics_->NotifyCorruptedProfile(); 1402ebc16da6068c8c61658b39cf70d157d7d0911ebPaul Stewart } 141b9c00597eb1f6d2560f7e88cb0d1f627228840d4Chris Masone return false; 142b9c00597eb1f6d2560f7e88cb0d1f627228840d4Chris Masone } 1435dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart if (!already_exists) { 1445dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart // Add a descriptive header to the profile so even if nothing is stored 1455dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart // to it, it still has some content. Completely empty keyfiles are not 1465dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart // valid for reading. 1475dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart storage->SetHeader( 1485dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart base::StringPrintf("Profile %s:%s", name_.user.c_str(), 1495dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart name_.identifier.c_str())); 1505dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart } 151b9c00597eb1f6d2560f7e88cb0d1f627228840d4Chris Masone set_storage(storage.release()); 1529842441bbfae81053a6c08045f1d7b831e5101b2mukesh agrawal manager_->OnProfileStorageInitialized(this); 153b9c00597eb1f6d2560f7e88cb0d1f627228840d4Chris Masone return true; 154b9c00597eb1f6d2560f7e88cb0d1f627228840d4Chris Masone} 155b9c00597eb1f6d2560f7e88cb0d1f627228840d4Chris Masone 15692496a43b023b912f7f251d0167be360b3335690mukesh agrawalvoid Profile::InitStubStorage() { 15792496a43b023b912f7f251d0167be360b3335690mukesh agrawal set_storage(new StubStorage()); 15892496a43b023b912f7f251d0167be360b3335690mukesh agrawal} 15992496a43b023b912f7f251d0167be360b3335690mukesh agrawal 160c80c460b90378124cc945b0b1f619d86949000a7mukesh agrawalbool Profile::RemoveStorage(Error* error) { 161e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart CHECK(!storage_.get()); 162e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal CHECK(!persistent_profile_path_.empty()); 163e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart 164e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal if (!base::DeleteFile(persistent_profile_path_, false)) { 165e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart Error::PopulateAndLog( 16634f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart FROM_HERE, error, Error::kOperationFailed, 167e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal base::StringPrintf("Could not remove path %s", 168e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal persistent_profile_path_.value().c_str())); 169e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart return false; 170e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart } 171e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart 172e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart return true; 173e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart} 174e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart 1757df0c672458bee8f4ff33004103351d59a9f4b50Chris Masonestring Profile::GetFriendlyName() { 1767df0c672458bee8f4ff33004103351d59a9f4b50Chris Masone return (name_.user.empty() ? "" : name_.user + "/") + name_.identifier; 1777df0c672458bee8f4ff33004103351d59a9f4b50Chris Masone} 1787df0c672458bee8f4ff33004103351d59a9f4b50Chris Masone 1797df0c672458bee8f4ff33004103351d59a9f4b50Chris Masonestring Profile::GetRpcIdentifier() { 18019c871da666a307fdf4e5bced0d745abefe9a04aPaul Stewart if (!adaptor_.get()) { 18191a5fecf9301440e22bd4a144acdb22558b7ec5ePeter Qiu return string(); 18219c871da666a307fdf4e5bced0d745abefe9a04aPaul Stewart } 1837df0c672458bee8f4ff33004103351d59a9f4b50Chris Masone return adaptor_->GetRpcIdentifier(); 1847df0c672458bee8f4ff33004103351d59a9f4b50Chris Masone} 1857df0c672458bee8f4ff33004103351d59a9f4b50Chris Masone 1861a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartvoid Profile::set_storage(StoreInterface* storage) { 187b9c00597eb1f6d2560f7e88cb0d1f627228840d4Chris Masone storage_.reset(storage); 188b9c00597eb1f6d2560f7e88cb0d1f627228840d4Chris Masone} 189b9c00597eb1f6d2560f7e88cb0d1f627228840d4Chris Masone 1901a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool Profile::AdoptService(const ServiceRefPtr& service) { 191451aa7f3e44642da0598c526030b41c6963c55d3Paul Stewart if (service->profile() == this) { 1926791a43add38926966bd420e89541717fb2cb2b5Chris Masone return false; 193451aa7f3e44642da0598c526030b41c6963c55d3Paul Stewart } 1947917360b71c6680de60b487b3630dc1a0f8cdca2Philipp Neubeck service->SetProfile(this); 1956515aabcd1fbbb9ff2090c9675c17eeef64e7474Chris Masone return service->Save(storage_.get()) && storage_->Flush(); 1966791a43add38926966bd420e89541717fb2cb2b5Chris Masone} 1976791a43add38926966bd420e89541717fb2cb2b5Chris Masone 1981a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool Profile::AbandonService(const ServiceRefPtr& service) { 1996515aabcd1fbbb9ff2090c9675c17eeef64e7474Chris Masone if (service->profile() == this) 200cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan service->SetProfile(nullptr); 2016515aabcd1fbbb9ff2090c9675c17eeef64e7474Chris Masone return storage_->DeleteGroup(service->GetStorageIdentifier()) && 2026515aabcd1fbbb9ff2090c9675c17eeef64e7474Chris Masone storage_->Flush(); 2036791a43add38926966bd420e89541717fb2cb2b5Chris Masone} 2046791a43add38926966bd420e89541717fb2cb2b5Chris Masone 2051a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool Profile::UpdateService(const ServiceRefPtr& service) { 2066515aabcd1fbbb9ff2090c9675c17eeef64e7474Chris Masone return service->Save(storage_.get()) && storage_->Flush(); 2076791a43add38926966bd420e89541717fb2cb2b5Chris Masone} 2086791a43add38926966bd420e89541717fb2cb2b5Chris Masone 2091a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool Profile::LoadService(const ServiceRefPtr& service) { 210bba6a5b87cb21424770228cd73e10574a2151568Paul Stewart if (!ContainsService(service)) 2116515aabcd1fbbb9ff2090c9675c17eeef64e7474Chris Masone return false; 2126515aabcd1fbbb9ff2090c9675c17eeef64e7474Chris Masone return service->Load(storage_.get()); 2136791a43add38926966bd420e89541717fb2cb2b5Chris Masone} 2146791a43add38926966bd420e89541717fb2cb2b5Chris Masone 2151a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool Profile::ConfigureService(const ServiceRefPtr& service) { 2162c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart if (!LoadService(service)) 2172c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart return false; 2182c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart service->SetProfile(this); 2192c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart return true; 2202c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart} 2212c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart 2221a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool Profile::ConfigureDevice(const DeviceRefPtr& device) { 223a41e38d57e4fa37bd2c8de6447890b4e1951acb7Paul Stewart return device->Load(storage_.get()); 224a41e38d57e4fa37bd2c8de6447890b4e1951acb7Paul Stewart} 225a41e38d57e4fa37bd2c8de6447890b4e1951acb7Paul Stewart 2261a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool Profile::ContainsService(const ServiceConstRefPtr& service) { 227e7de2942df36080268c1f296b40e28480479187cPaul Stewart return service->IsLoadableFrom(*storage_.get()); 2287aa5f90848b530999d8b6788ecb40aa30871c7aeChris Masone} 2297aa5f90848b530999d8b6788ecb40aa30871c7aeChris Masone 2301a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartvoid Profile::DeleteEntry(const std::string& entry_name, Error* error) { 2317522551440b9a287bccf2d95a42357d04ab79814Paul Stewart if (!storage_->ContainsGroup(entry_name)) { 23234f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart Error::PopulateAndLog( 23334f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart FROM_HERE, error, Error::kNotFound, 2347522551440b9a287bccf2d95a42357d04ab79814Paul Stewart base::StringPrintf("Entry %s does not exist in profile", 2357522551440b9a287bccf2d95a42357d04ab79814Paul Stewart entry_name.c_str())); 2367522551440b9a287bccf2d95a42357d04ab79814Paul Stewart return; 2377522551440b9a287bccf2d95a42357d04ab79814Paul Stewart } 2387522551440b9a287bccf2d95a42357d04ab79814Paul Stewart if (!manager_->HandleProfileEntryDeletion(this, entry_name)) { 2397522551440b9a287bccf2d95a42357d04ab79814Paul Stewart // If HandleProfileEntryDeletion() returns succeeds, DeleteGroup() 2407522551440b9a287bccf2d95a42357d04ab79814Paul Stewart // has already been called when AbandonService was called. 2417522551440b9a287bccf2d95a42357d04ab79814Paul Stewart // Otherwise, we need to delete the group ourselves. 2427522551440b9a287bccf2d95a42357d04ab79814Paul Stewart storage_->DeleteGroup(entry_name); 2437522551440b9a287bccf2d95a42357d04ab79814Paul Stewart } 2440756db95c9d39d6e6aa9a754e54b441eff46ff34Paul Stewart Save(); 2450756db95c9d39d6e6aa9a754e54b441eff46ff34Paul Stewart} 2460756db95c9d39d6e6aa9a754e54b441eff46ff34Paul Stewart 2471a212a6b98b22ad1d69652bb26a9e94138635476Paul StewartServiceRefPtr Profile::GetServiceFromEntry(const std::string& entry_name, 2481a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart Error* error) { 24918213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu if (!storage_->ContainsGroup(entry_name)) { 25018213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu Error::PopulateAndLog( 25118213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu FROM_HERE, error, Error::kNotFound, 25218213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu base::StringPrintf("Entry %s does not exist in profile", 25318213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu entry_name.c_str())); 25418213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu return nullptr; 25518213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu } 25618213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu 25718213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu // Lookup the service entry from the registered services. 25818213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu ServiceRefPtr service = 25918213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu manager_->GetServiceWithStorageIdentifier(this, entry_name, error); 26018213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu if (service) { 26118213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu return service; 26218213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu } 26318213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu 26418213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu // Load the service entry to a temporary service. 26518213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu return manager_->CreateTemporaryServiceFromProfile(this, entry_name, error); 2667522551440b9a287bccf2d95a42357d04ab79814Paul Stewart} 2677522551440b9a287bccf2d95a42357d04ab79814Paul Stewart 2681a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool Profile::IsValidIdentifierToken(const string& token) { 269a4766822880815bafdc69778ccaccaf661536181Darin Petkov if (token.empty()) { 270a4766822880815bafdc69778ccaccaf661536181Darin Petkov return false; 271a4766822880815bafdc69778ccaccaf661536181Darin Petkov } 2726db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart for (auto chr : token) { 2733a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko if (!base::IsAsciiAlpha(chr) && !base::IsAsciiDigit(chr)) { 274a4766822880815bafdc69778ccaccaf661536181Darin Petkov return false; 275a4766822880815bafdc69778ccaccaf661536181Darin Petkov } 276a4766822880815bafdc69778ccaccaf661536181Darin Petkov } 277a4766822880815bafdc69778ccaccaf661536181Darin Petkov return true; 278a4766822880815bafdc69778ccaccaf661536181Darin Petkov} 279a4766822880815bafdc69778ccaccaf661536181Darin Petkov 280f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart// static 2811a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool Profile::ParseIdentifier(const string& raw, Identifier* parsed) { 282a4766822880815bafdc69778ccaccaf661536181Darin Petkov if (raw.empty()) { 283a4766822880815bafdc69778ccaccaf661536181Darin Petkov return false; 284a4766822880815bafdc69778ccaccaf661536181Darin Petkov } 285a4766822880815bafdc69778ccaccaf661536181Darin Petkov if (raw[0] == '~') { 286a4766822880815bafdc69778ccaccaf661536181Darin Petkov // Format: "~user/identifier". 287a4766822880815bafdc69778ccaccaf661536181Darin Petkov size_t slash = raw.find('/'); 288a4766822880815bafdc69778ccaccaf661536181Darin Petkov if (slash == string::npos) { 289a4766822880815bafdc69778ccaccaf661536181Darin Petkov return false; 290a4766822880815bafdc69778ccaccaf661536181Darin Petkov } 291a4766822880815bafdc69778ccaccaf661536181Darin Petkov string user(raw.begin() + 1, raw.begin() + slash); 292a4766822880815bafdc69778ccaccaf661536181Darin Petkov string identifier(raw.begin() + slash + 1, raw.end()); 293a4766822880815bafdc69778ccaccaf661536181Darin Petkov if (!IsValidIdentifierToken(user) || !IsValidIdentifierToken(identifier)) { 294a4766822880815bafdc69778ccaccaf661536181Darin Petkov return false; 295a4766822880815bafdc69778ccaccaf661536181Darin Petkov } 296a4766822880815bafdc69778ccaccaf661536181Darin Petkov parsed->user = user; 297a4766822880815bafdc69778ccaccaf661536181Darin Petkov parsed->identifier = identifier; 298a4766822880815bafdc69778ccaccaf661536181Darin Petkov return true; 299a4766822880815bafdc69778ccaccaf661536181Darin Petkov } 300a4766822880815bafdc69778ccaccaf661536181Darin Petkov 301a4766822880815bafdc69778ccaccaf661536181Darin Petkov // Format: "identifier". 302a4766822880815bafdc69778ccaccaf661536181Darin Petkov if (!IsValidIdentifierToken(raw)) { 303a4766822880815bafdc69778ccaccaf661536181Darin Petkov return false; 304a4766822880815bafdc69778ccaccaf661536181Darin Petkov } 305a4766822880815bafdc69778ccaccaf661536181Darin Petkov parsed->user = ""; 306a4766822880815bafdc69778ccaccaf661536181Darin Petkov parsed->identifier = raw; 307a4766822880815bafdc69778ccaccaf661536181Darin Petkov return true; 308a4766822880815bafdc69778ccaccaf661536181Darin Petkov} 309a4766822880815bafdc69778ccaccaf661536181Darin Petkov 310f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart// static 3111a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartstring Profile::IdentifierToString(const Identifier& name) { 312f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart if (name.user.empty()) { 313f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart // Format: "identifier". 314f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart return name.identifier; 315f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart } 316f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart 317f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart // Format: "~user/identifier". 318f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart return base::StringPrintf( 319f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart "~%s/%s", name.user.c_str(), name.identifier.c_str()); 320f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart} 321f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart 32278af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart// static 3231a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartvector<Profile::Identifier> Profile::LoadUserProfileList(const FilePath& path) { 32478af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart vector<Identifier> profile_identifiers; 32578af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart string profile_data; 326a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan if (!base::ReadFileToString(path, &profile_data)) { 32778af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart return profile_identifiers; 32878af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart } 32978af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart 3303a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko vector<string> profile_lines = 3313a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko base::SplitString(profile_data, "\n", base::KEEP_WHITESPACE, 3323a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko base::SPLIT_WANT_ALL); 3331a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart for (const auto& line : profile_lines) { 33478af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart if (line.empty()) { 33578af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart // This will be the case on the last line, so let's not complain about it. 33678af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart continue; 33778af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart } 33878af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart size_t space = line.find(' '); 33978af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart if (space == string::npos || space == 0) { 34078af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart LOG(ERROR) << "Invalid line found in " << path.value() 34178af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart << ": " << line; 34278af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart continue; 34378af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart } 34478af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart string name(line.begin(), line.begin() + space); 34578af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart Identifier identifier; 34678af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart if (!ParseIdentifier(name, &identifier) || identifier.user.empty()) { 34778af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart LOG(ERROR) << "Invalid profile name found in " << path.value() 34878af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart << ": " << name; 34978af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart continue; 35078af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart } 35178af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart identifier.user_hash = string(line.begin() + space + 1, line.end()); 35278af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart profile_identifiers.push_back(identifier); 35378af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart } 35478af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart 35578af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart return profile_identifiers; 35678af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart} 35778af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart 35878af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart// static 3591a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool Profile::SaveUserProfileList(const FilePath& path, 3601a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart const vector<ProfileRefPtr>& profiles) { 36178af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart vector<string> lines; 3621a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart for (const auto& profile : profiles) { 3631a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart Identifier& id = profile->name_; 36478af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart if (id.user.empty()) { 36578af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart continue; 36678af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart } 36778af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart lines.push_back(base::StringPrintf("%s %s\n", 36878af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart IdentifierToString(id).c_str(), 36978af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart id.user_hash.c_str())); 37078af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart } 3713a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko string content = base::JoinString(lines, ""); 3726fbf64f493a9aae7d743888039c61a57386203dbBen Chan size_t ret = base::WriteFile(path, content.c_str(), content.length()); 37378af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart return ret == content.length(); 37478af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart} 37578af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart 3761a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool Profile::MatchesIdentifier(const Identifier& name) const { 3775dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart return name.user == name_.user && name.identifier == name_.identifier; 3785dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart} 3795dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart 380b9c00597eb1f6d2560f7e88cb0d1f627228840d4Chris Masonebool Profile::Save() { 3816515aabcd1fbbb9ff2090c9675c17eeef64e7474Chris Masone return storage_->Flush(); 3829d779936d8f8c2d74b30883e2a2622c4207fe797Chris Masone} 3839d779936d8f8c2d74b30883e2a2622c4207fe797Chris Masone 3841a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartvector<string> Profile::EnumerateAvailableServices(Error* error) { 3851b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart // We should return the Manager's service list if this is the active profile. 3861b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart if (manager_->IsActiveProfile(this)) { 3871b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart return manager_->EnumerateAvailableServices(error); 3881b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart } else { 3891b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart return vector<string>(); 3901b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart } 3916791a43add38926966bd420e89541717fb2cb2b5Chris Masone} 3926791a43add38926966bd420e89541717fb2cb2b5Chris Masone 3931a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartvector<string> Profile::EnumerateEntries(Error* /*error*/) { 3941b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart vector<string> service_groups; 3951b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart 3961b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart // Filter this list down to only entries that correspond 3971b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart // to a technology. (wifi_*, etc) 3981a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart for (const auto& group : storage_->GetGroups()) { 3996db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart if (Technology::IdentifierFromStorageGroup(group) != Technology::kUnknown) 4006db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart service_groups.push_back(group); 4011b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart } 4021b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart 4031b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart return service_groups; 4046791a43add38926966bd420e89541717fb2cb2b5Chris Masone} 4056791a43add38926966bd420e89541717fb2cb2b5Chris Masone 4061a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool Profile::UpdateDevice(const DeviceRefPtr& device) { 407e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov return false; 408e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov} 409e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov 4101a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIFI) 4111a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool Profile::UpdateWiFiProvider(const WiFiProvider& wifi_provider) { 41260a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie return false; 41360a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie} 4141a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif // DISABLE_WIFI 41560a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie 416bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawalvoid Profile::HelpRegisterConstDerivedStrings( 4171a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart const string& name, 4181a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart Strings(Profile::*get)(Error*)) { 4196791a43add38926966bd420e89541717fb2cb2b5Chris Masone store_.RegisterDerivedStrings( 420cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan name, StringsAccessor( 421cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan new CustomAccessor<Profile, Strings>(this, get, nullptr))); 4226791a43add38926966bd420e89541717fb2cb2b5Chris Masone} 4236791a43add38926966bd420e89541717fb2cb2b5Chris Masone 424e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal// static 425e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawalFilePath Profile::GetFinalStoragePath( 426e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal const FilePath& storage_dir, 427e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal const Identifier& profile_name) { 428e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal FilePath base_path; 429e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal if (profile_name.user.empty()) { // True for DefaultProfiles. 430e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal base_path = storage_dir.Append( 431e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal base::StringPrintf("%s.profile", profile_name.identifier.c_str())); 432e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal } else { 433e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal base_path = storage_dir.Append( 434e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal base::StringPrintf("%s/%s.profile", 435e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal profile_name.user.c_str(), 436e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal profile_name.identifier.c_str())); 437e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal } 438e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal 439e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal // TODO(petkov): Validate the directory permissions, etc. 440e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal 441e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal#if defined(ENABLE_JSON_STORE) 442e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal return base_path.AddExtension(kFileExtensionJson); 443e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal#else 444e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal return base_path; 445e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal#endif 446e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal} 447e48186532acb04b9e11efc9b9334dd555ffcae29mukesh agrawal 44852cd19bfd52226611d924930f1178307f79d5fdcChris Masone} // namespace shill 449