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//
1675897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart
178fe2c7eea92541b5282929361a19ad519e0608a9Chris Masone#include "shill/manager.h"
188fe2c7eea92541b5282929361a19ad519e0608a9Chris Masone
1975897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart#include <stdio.h>
20a41ab517725d036b63420f8445550246f8f50b99Alex Vakulenko#include <time.h>
21ee929b7ab2a89bbf2d1aecf85bbd49e53fbea059Chris Masone
2222aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart#include <algorithm>
23df7c553368620f718ec14bc6751f232185792870Jason Glasgow#include <set>
2475897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart#include <string>
2552cd19bfd52226611d924930f1178307f79d5fdcChris Masone#include <vector>
2675897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart
273e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood#include <base/bind.h>
28c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu#include <base/callback.h>
2911c213f3cf64f27a0e42ee6da95e98bd1d4b3202Ben Chan#include <base/files/file_util.h>
309be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone#include <base/memory/ref_counted.h>
313a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko#include <base/strings/pattern.h>
32a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/stringprintf.h>
33a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_split.h>
34a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_util.h>
35289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#if defined(__ANDROID__)
36289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#include <dbus/service_constants.h>
37289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#else
383bd3c8c33917221d1074f1aa19272e45c0ce2793Chris Masone#include <chromeos/dbus/service_constants.h>
39289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#endif  // __ANDROID__
40ee929b7ab2a89bbf2d1aecf85bbd49e53fbea059Chris Masone
41d0ceb8c66779819ab12b8abb488aed22b7d04fd3Chris Masone#include "shill/adaptor_interfaces.h"
4246c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal#include "shill/callbacks.h"
43c1dec4d5cad7c6ee2cd8dbc4f47e4d30403dcca1Paul Stewart#include "shill/connection.h"
4475897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart#include "shill/control_interface.h"
457aa5f90848b530999d8b6788ecb40aa30871c7aeChris Masone#include "shill/default_profile.h"
469be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone#include "shill/device.h"
477e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu#include "shill/device_claimer.h"
489be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone#include "shill/device_info.h"
496791a43add38926966bd420e89541717fb2cb2b5Chris Masone#include "shill/ephemeral_profile.h"
508fe2c7eea92541b5282929361a19ad519e0608a9Chris Masone#include "shill/error.h"
516fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu#include "shill/ethernet/ethernet_temporary_service.h"
5226b327e559583d5a84b7e1605c29a4dcbc87d2a9Paul Stewart#include "shill/event_dispatcher.h"
53b790aa2e5b6422cbba4a20be81ba1c0445701405Gaurav Shah#include "shill/geolocation_info.h"
54a9fb325a645e0be17b3eaa26a4d0f1d5228683c9Gary Morain#include "shill/hook_table.h"
55ba99b598d3f399a41e57f49dccac5f988e653126Prathmesh Prabhu#include "shill/ip_address_store.h"
56b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley#include "shill/logging.h"
577aa5f90848b530999d8b6788ecb40aa30871c7aeChris Masone#include "shill/profile.h"
58b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone#include "shill/property_accessor.h"
59e613202d36e3bfb06a40eea1888694413210ef7ePaul Stewart#include "shill/resolver.h"
6046c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal#include "shill/result_aggregator.h"
619be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone#include "shill/service.h"
62a20cbc2864edf5491cfa1fa240ba83c30b8a483cThieu Le#include "shill/service_sorter.h"
6304147470fdeaaf9ab7588bd3a7988d74aa990068mukesh agrawal#include "shill/store_factory.h"
642240e8c03451c6b6f21eb8944d8a1c0747ac10b3Ben Chan#include "shill/vpn/vpn_provider.h"
652240e8c03451c6b6f21eb8944d8a1c0747ac10b3Ben Chan#include "shill/vpn/vpn_service.h"
661a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#include "shill/wimax/wimax_service.h"
671a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu
6895522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu#if defined(__BRILLO__)
6995522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu#include "shill/wifi/wifi_driver_hal.h"
7095522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu#endif  // __BRILLO__
7195522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu
721a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIFI)
73d6a8b519e3057f52313e502f502a4819a942e089Ben Chan#include "shill/wifi/wifi.h"
74d6a8b519e3057f52313e502f502a4819a942e089Ben Chan#include "shill/wifi/wifi_provider.h"
75d6a8b519e3057f52313e502f502a4819a942e089Ben Chan#include "shill/wifi/wifi_service.h"
761a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif  // DISABLE_WIFI
771a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu
781a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIRED_8021X)
791a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#include "shill/ethernet/ethernet_eap_provider.h"
801a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#include "shill/ethernet/ethernet_eap_service.h"
811a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif  // DISABLE_WIRED_8021X
8275897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart
833e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Bind;
84c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiuusing base::Callback;
850e1cdeae24dd678a5fe27c840802582c0ca45ec0Albert Chaulkusing base::FilePath;
863e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::StringPrintf;
873e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Unretained;
88a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkovusing std::map;
89435de2cd55a95836381b53acbce8cbbad98ec04dGaurav Shahusing std::set;
9075897df1154ac38b7a4512a687241ad6a197ee40Paul Stewartusing std::string;
919be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masoneusing std::vector;
9275897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart
9375897df1154ac38b7a4512a687241ad6a197ee40Paul Stewartnamespace shill {
94e613202d36e3bfb06a40eea1888694413210ef7ePaul Stewart
95c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silbersteinnamespace Logging {
96c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silbersteinstatic auto kModuleLogScope = ScopeLogger::kManager;
978ae18741780300de3126826b72593391f2d00313Paul Stewartstatic string ObjectID(const Manager* m) { return "manager"; }
98c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein}
99c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein
100c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein
101b65c24574109b331150f376f117e10948acc7123Darin Petkov// statics
102b65c24574109b331150f376f117e10948acc7123Darin Petkovconst char Manager::kErrorNoDevice[] = "no wifi devices available";
103b65c24574109b331150f376f117e10948acc7123Darin Petkovconst char Manager::kErrorTypeRequired[] = "must specify service type";
104b65c24574109b331150f376f117e10948acc7123Darin Petkovconst char Manager::kErrorUnsupportedServiceType[] =
105b65c24574109b331150f376f117e10948acc7123Darin Petkov    "service type is unsupported";
106ab22c166ccfb33fd99169bee645d67306ae26cedArman Uguray// This timeout should be less than the upstart job timeout, otherwise
107ab22c166ccfb33fd99169bee645d67306ae26cedArman Uguray// stats for termination actions might be lost.
108ea7dcda5aae9c2579f16b142e5832e8aa7bd7ec4Samuel Tanconst int Manager::kTerminationActionsTimeoutMilliseconds = 19500;
1097a4e4008dc09effe39c94a5f9575644a79ee1388mukesh agrawal
11094d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu// Device status check interval (every 3 minutes).
11194d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiuconst int Manager::kDeviceStatusCheckIntervalMilliseconds = 180000;
11294d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu
11394d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu// static
1148ae18741780300de3126826b72593391f2d00313Paul Stewartconst char* Manager::kProbeTechnologies[] = {
11594d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu    kTypeEthernet,
11694d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu    kTypeWifi,
11794d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu    kTypeWimax,
11894d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu    kTypeCellular
11994d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu};
120700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu
1211d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu// static
1221d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiuconst char Manager::kDefaultClaimerName[] = "";
1231d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu
1248ae18741780300de3126826b72593391f2d00313Paul StewartManager::Manager(ControlInterface* control_interface,
1258ae18741780300de3126826b72593391f2d00313Paul Stewart                 EventDispatcher* dispatcher,
1268ae18741780300de3126826b72593391f2d00313Paul Stewart                 Metrics* metrics,
1278ae18741780300de3126826b72593391f2d00313Paul Stewart                 const string& run_directory,
1288ae18741780300de3126826b72593391f2d00313Paul Stewart                 const string& storage_directory,
1298ae18741780300de3126826b72593391f2d00313Paul Stewart                 const string& user_storage_directory)
1308a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal    : dispatcher_(dispatcher),
1318a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal      run_path_(FilePath(run_directory)),
1328a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal      storage_path_(FilePath(storage_directory)),
1330a59a5a484634f798222ad077dbbfa7faa76651dmukesh agrawal      user_storage_path_(user_storage_directory),
134d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal      user_profile_list_path_(FilePath(Profile::kUserProfileListPathname)),
1358a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal      adaptor_(control_interface->CreateManagerAdaptor(this)),
1363426c8fc7a3943f2d8fcb2ec78f0593088b42bedThieu Le      device_info_(control_interface, dispatcher, metrics, this),
1375742b24ab984464701fef0cc7024af2637357b04Ben Chan#if !defined(DISABLE_CELLULAR)
138bad1c10ffd2d4ac14f7bd9f4ef6a8982e711f566mukesh agrawal      modem_info_(control_interface, dispatcher, metrics, this),
1395742b24ab984464701fef0cc7024af2637357b04Ben Chan#endif  // DISABLE_CELLULAR
1401a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIRED_8021X)
14135eff134fd95fdf1918803c4966f8b790914b3d4Paul Stewart      ethernet_eap_provider_(
14235eff134fd95fdf1918803c4966f8b790914b3d4Paul Stewart          new EthernetEapProvider(
14335eff134fd95fdf1918803c4966f8b790914b3d4Paul Stewart              control_interface, dispatcher, metrics, this)),
1441a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif  // DISABLE_WIRED_8021X
145c3505a569e3f98ce56e4017300a3ce46bc714e4cDarin Petkov      vpn_provider_(
146c3505a569e3f98ce56e4017300a3ce46bc714e4cDarin Petkov          new VPNProvider(control_interface, dispatcher, metrics, this)),
1471a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIFI)
1483c5040174273386868cc8dea8044d22c465885d8Paul Stewart      wifi_provider_(
1493c5040174273386868cc8dea8044d22c465885d8Paul Stewart          new WiFiProvider(control_interface, dispatcher, metrics, this)),
150d13249c35eb0c5281c422a3c17a252b5cc8c865dPeter Qiu#if defined(__BRILLO__)
151d13249c35eb0c5281c422a3c17a252b5cc8c865dPeter Qiu      wifi_driver_hal_(WiFiDriverHal::GetInstance()),
152d13249c35eb0c5281c422a3c17a252b5cc8c865dPeter Qiu#endif  // __BRILLO__
1531a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif  // DISABLE_WIFI
154520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan#if !defined(DISABLE_WIMAX)
155b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart      wimax_provider_(
156b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart          new WiMaxProvider(control_interface, dispatcher, metrics, this)),
157520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan#endif  // DISABLE_WIMAX
1584d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart      resolver_(Resolver::GetInstance()),
1598a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal      running_(false),
1608a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal      connect_profiles_to_rpc_(true),
1615133b71eaa00535739ebbddd8a8f31cd8fcf33a8Thieu Le      ephemeral_profile_(
1625133b71eaa00535739ebbddd8a8f31cd8fcf33a8Thieu Le          new EphemeralProfile(control_interface, metrics, this)),
1638a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal      control_interface_(control_interface),
1643426c8fc7a3943f2d8fcb2ec78f0593088b42bedThieu Le      metrics_(metrics),
165a9fb325a645e0be17b3eaa26a4d0f1d5228683c9Gary Morain      use_startup_portal_list_(false),
16694d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu      device_status_check_task_(Bind(&Manager::DeviceStatusCheckTask,
16794d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu                                     base::Unretained(this))),
168a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov      termination_actions_(dispatcher),
1690818cca76b252080dc78f10e6c4c7c4580a226fcDaniel Erat      suspend_delay_registered_(false),
1708e9e41cedee1a6be89ebc027afab62c9a52cb574Paul Stewart      is_wake_on_lan_enabled_(true),
17183d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewart      ignore_unknown_ethernet_(false),
1721057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley      default_service_callback_tag_(0),
17313d581fa047118d065f41eb1d0da203cf0a49b07mukesh agrawal      crypto_util_proxy_(new CryptoUtilProxy(dispatcher)),
174381a0bb9927ded7963004fcd6793a77a3fca327bSamuel Tan      health_checker_remote_ips_(new IPAddressStore()),
1752b35cfb222200f9d7bac73f68038e9126146ae5eRoshan Pius      suppress_autoconnect_(false),
17615d5431798155cc83a3fcb8abe0d1a2d5128f7b6Rebecca Silberstein      is_connected_state_(false),
17715d5431798155cc83a3fcb8abe0d1a2d5128f7b6Rebecca Silberstein      dhcp_properties_(new DhcpProperties()) {
178923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  HelpRegisterDerivedString(kActiveProfileProperty,
1791b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart                            &Manager::GetActiveProfileRpcIdentifier,
180cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan                            nullptr);
181923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  store_.RegisterBool(kArpGatewayProperty, &props_.arp_gateway);
182923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  HelpRegisterConstDerivedStrings(kAvailableTechnologiesProperty,
183bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal                                  &Manager::AvailableTechnologies);
184923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  HelpRegisterDerivedString(kCheckPortalListProperty,
18510e9e4e93537a0673524d47535cbf0f723470a0dPaul Stewart                            &Manager::GetCheckPortalList,
18610e9e4e93537a0673524d47535cbf0f723470a0dPaul Stewart                            &Manager::SetCheckPortalList);
187923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  HelpRegisterConstDerivedStrings(kConnectedTechnologiesProperty,
188bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal                                  &Manager::ConnectedTechnologies);
18903e29f77413e978ecfbd46e51979916f6e7ebff8Paul Stewart  store_.RegisterConstString(kConnectionStateProperty, &connection_state_);
190923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  store_.RegisterString(kCountryProperty, &props_.country);
191923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  HelpRegisterDerivedString(kDefaultTechnologyProperty,
19227c4aa55b33d3a3836cf70c8f7094bce1c5ead8cChris Masone                            &Manager::DefaultTechnology,
193cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan                            nullptr);
19449739c08a76187fae6494c61e960eec315960715Paul Stewart  HelpRegisterConstDerivedRpcIdentifier(
19539a7beb18a0c24c9b73c3cc49008ccdca19f9ac2Ben Chan      kDefaultServiceProperty, &Manager::GetDefaultServiceRpcIdentifier);
196923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  HelpRegisterConstDerivedRpcIdentifiers(kDevicesProperty,
197cb3eb8970ee676be0e5738d62685f9e0a2d7cb73Paul Stewart                                         &Manager::EnumerateDevices);
1981a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIFI)
1999d97b7deda3ae604d718873207a951f62d418b34Paul Stewart  HelpRegisterDerivedBool(kDisableWiFiVHTProperty,
2009d97b7deda3ae604d718873207a951f62d418b34Paul Stewart                          &Manager::GetDisableWiFiVHT,
2019d97b7deda3ae604d718873207a951f62d418b34Paul Stewart                          &Manager::SetDisableWiFiVHT);
2021a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif  // DISABLE_WIFI
203923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  HelpRegisterConstDerivedStrings(kEnabledTechnologiesProperty,
204bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal                                  &Manager::EnabledTechnologies);
20539a7beb18a0c24c9b73c3cc49008ccdca19f9ac2Ben Chan  HelpRegisterDerivedString(kIgnoredDNSSearchPathsProperty,
2064d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart                            &Manager::GetIgnoredDNSSearchPaths,
2074d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart                            &Manager::SetIgnoredDNSSearchPaths);
208ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  store_.RegisterString(kHostNameProperty, &props_.host_name);
20939a7beb18a0c24c9b73c3cc49008ccdca19f9ac2Ben Chan  store_.RegisterString(kLinkMonitorTechnologiesProperty,
210036dba0c6641acdbe02d52260c6fa6dca84b1af2Paul Stewart                        &props_.link_monitor_technologies);
2118e6b8ef22e185310480c13aa3a6e89184cce62d1Ben Chan  store_.RegisterString(kNoAutoConnectTechnologiesProperty,
2128e6b8ef22e185310480c13aa3a6e89184cce62d1Ben Chan                        &props_.no_auto_connect_technologies);
213923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  store_.RegisterBool(kOfflineModeProperty, &props_.offline_mode);
214923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  store_.RegisterString(kPortalURLProperty, &props_.portal_url);
215c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart  store_.RegisterInt32(kPortalCheckIntervalProperty,
216c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart                       &props_.portal_check_interval_seconds);
217923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  HelpRegisterConstDerivedRpcIdentifiers(kProfilesProperty,
218cb3eb8970ee676be0e5738d62685f9e0a2d7cb73Paul Stewart                                         &Manager::EnumerateProfiles);
219ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  HelpRegisterDerivedString(kProhibitedTechnologiesProperty,
220ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart                            &Manager::GetProhibitedTechnologies,
221ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart                            &Manager::SetProhibitedTechnologies);
222923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  HelpRegisterDerivedString(kStateProperty,
22327c4aa55b33d3a3836cf70c8f7094bce1c5ead8cChris Masone                            &Manager::CalculateState,
224cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan                            nullptr);
225923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  HelpRegisterConstDerivedRpcIdentifiers(kServicesProperty,
2262366eede28daa298f240ddbc3c8f36cc0e7b7ad1mukesh agrawal                                         &Manager::EnumerateAvailableServices);
22739a7beb18a0c24c9b73c3cc49008ccdca19f9ac2Ben Chan  HelpRegisterConstDerivedRpcIdentifiers(kServiceCompleteListProperty,
2283c5040174273386868cc8dea8044d22c465885d8Paul Stewart                                         &Manager::EnumerateCompleteServices);
229923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  HelpRegisterConstDerivedRpcIdentifiers(kServiceWatchListProperty,
230cb3eb8970ee676be0e5738d62685f9e0a2d7cb73Paul Stewart                                         &Manager::EnumerateWatchedServices);
231bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  HelpRegisterConstDerivedStrings(kUninitializedTechnologiesProperty,
232bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal                                  &Manager::UninitializedTechnologies);
2338e9e41cedee1a6be89ebc027afab62c9a52cb574Paul Stewart  store_.RegisterBool(kWakeOnLanEnabledProperty, &is_wake_on_lan_enabled_);
234babfe5a5e1f7b11a70fdf616b8479166416810c9Garret Kelly  HelpRegisterConstDerivedStrings(kClaimedDevicesProperty,
235babfe5a5e1f7b11a70fdf616b8479166416810c9Garret Kelly                                  &Manager::ClaimedDevices);
2363c3f6a1dcc0533545f7efb5ffed5a3edc089f240Chris Masone
237b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart  UpdateProviderMapping();
238b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart
23915d5431798155cc83a3fcb8abe0d1a2d5128f7b6Rebecca Silberstein  dhcp_properties_->InitPropertyStore(&store_);
24015d5431798155cc83a3fcb8abe0d1a2d5128f7b6Rebecca Silberstein
241c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << "Manager initialized.";
24275897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart}
24375897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart
244e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin PetkovManager::~Manager() {}
24575897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart
246c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiuvoid Manager::RegisterAsync(const Callback<void(bool)>& completion_callback) {
247c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu  adaptor_->RegisterAsync(completion_callback);
24869b6a95f893d2b21d66ca66a068ae9b1f3cd5470Peter Qiu}
24969b6a95f893d2b21d66ca66a068ae9b1f3cd5470Peter Qiu
25091b7150819b785f36c2c094ae4aa102336bd6f71Peter Qiuvoid Manager::SetBlacklistedDevices(const vector<string>& blacklisted_devices) {
25191b7150819b785f36c2c094ae4aa102336bd6f71Peter Qiu  blacklisted_devices_ = blacklisted_devices;
2528f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal}
2538f317b600a218afe05f2d73c59204bb98269a950mukesh agrawal
254c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grantvoid Manager::SetWhitelistedDevices(const vector<string>& whitelisted_devices) {
255c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant  whitelisted_devices_ = whitelisted_devices;
256c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant}
257c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant
25875897df1154ac38b7a4512a687241ad6a197ee40Paul Stewartvoid Manager::Start() {
2590af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart  LOG(INFO) << "Manager started.";
260e613202d36e3bfb06a40eea1888694413210ef7ePaul Stewart
2613ec553401f04d005cfce24411cd63929557dea75Darin Petkov  power_manager_.reset(
262608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu      new PowerManager(dispatcher_, control_interface_));
263c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu  power_manager_->Start(base::TimeDelta::FromMilliseconds(
2649fdb84ba0ac2eb56961c90bba592481af493a10fPrathmesh Prabhu                            kTerminationActionsTimeoutMilliseconds),
2659fdb84ba0ac2eb56961c90bba592481af493a10fPrathmesh Prabhu                        Bind(&Manager::OnSuspendImminent, AsWeakPtr()),
26664ad2383c4555a99f4f09fe8f5faa088f99f5b90Prathmesh Prabhu                        Bind(&Manager::OnSuspendDone, AsWeakPtr()),
26764ad2383c4555a99f4f09fe8f5faa088f99f5b90Prathmesh Prabhu                        Bind(&Manager::OnDarkSuspendImminent, AsWeakPtr()));
268608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu  upstart_.reset(new Upstart(control_interface_));
269b84ba34aec59d083980d840fb845a3e2bea893cbThieu Le
270a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan  CHECK(base::CreateDirectory(run_path_)) << run_path_.value();
2714d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart  resolver_->set_path(run_path_.Append("resolv.conf"));
2722ae797d040b7261a5619c750e07037566bcb542bChris Masone
273713547627a2d6dc731cc1a7c80d2df79bee68a5eGaurav Shah  InitializeProfiles();
27475897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart  running_ = true;
2750af98bf87e8fc3cf29293f62d7f3b73cd9adb571Paul Stewart  device_info_.Start();
2765742b24ab984464701fef0cc7024af2637357b04Ben Chan#if !defined(DISABLE_CELLULAR)
277887f2983bc84acc15139df257e43217fec1f6cdbDarin Petkov  modem_info_.Start();
2785742b24ab984464701fef0cc7024af2637357b04Ben Chan#endif  // DISABLE_CELLULAR
2798ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& provider_mapping : providers_) {
280b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart    provider_mapping.second->Start();
281b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart  }
282700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu
283700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu  // Start task for checking connection status.
28494d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu  dispatcher_->PostDelayedTask(device_status_check_task_.callback(),
28594d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu                               kDeviceStatusCheckIntervalMilliseconds);
28675897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart}
28775897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart
28875897df1154ac38b7a4512a687241ad6a197ee40Paul Stewartvoid Manager::Stop() {
28975897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart  running_ = false;
290212d60f4de8a17702dc824f4a56d7de884e18e27Paul Stewart  // Persist device information to disk;
2918ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
2926db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    UpdateDevice(device);
293212d60f4de8a17702dc824f4a56d7de884e18e27Paul Stewart  }
294212d60f4de8a17702dc824f4a56d7de884e18e27Paul Stewart
2951a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIFI)
29660a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie  UpdateWiFiProvider();
2971a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif  // DISABLE_WIFI
29860a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie
299212d60f4de8a17702dc824f4a56d7de884e18e27Paul Stewart  // Persist profile, service information to disk.
3008ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& profile : profiles_) {
301d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    // Since this happens in a loop, the current manager state is stored to
302d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    // all default profiles in the stack.  This is acceptable because the
303d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    // only time multiple default profiles are loaded are during autotests.
3046db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    profile->Save();
3059d779936d8f8c2d74b30883e2a2622c4207fe797Chris Masone  }
3069d779936d8f8c2d74b30883e2a2622c4207fe797Chris Masone
3070ed0f2e84c366a90bca4a824b0adf18e9f243369mukesh agrawal  Error e;
3088ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_) {
3090d06119be3224788ba1aa65ed24bc8e46b56b949Samuel Tan    service->Disconnect(&e, __func__);
3101271d6828b226f951fa69ed9927fa7c9a358318aThieu Le  }
3111271d6828b226f951fa69ed9927fa7c9a358318aThieu Le
3128ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
313a06c65fa73e48e6ed02156ba6d62dcea2739a1a2Paul Stewart    device->SetEnabled(false);
314a06c65fa73e48e6ed02156ba6d62dcea2739a1a2Paul Stewart  }
315a06c65fa73e48e6ed02156ba6d62dcea2739a1a2Paul Stewart
3168ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& provider_mapping : providers_) {
317b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart    provider_mapping.second->Stop();
318b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart  }
3195742b24ab984464701fef0cc7024af2637357b04Ben Chan#if !defined(DISABLE_CELLULAR)
320887f2983bc84acc15139df257e43217fec1f6cdbDarin Petkov  modem_info_.Stop();
3215742b24ab984464701fef0cc7024af2637357b04Ben Chan#endif  // DISABLE_CELLULAR
322887f2983bc84acc15139df257e43217fec1f6cdbDarin Petkov  device_info_.Stop();
32394d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu  device_status_check_task_.Cancel();
324dfa46057cfb0a3af99d326694e2537f1189dcc06Paul Stewart  sort_services_task_.Cancel();
3259fdb84ba0ac2eb56961c90bba592481af493a10fPrathmesh Prabhu  power_manager_->Stop();
326ca62154261be3d481c1e54d5fcf7012e8918b4e2Darin Petkov  power_manager_.reset();
32775897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart}
32875897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart
329713547627a2d6dc731cc1a7c80d2df79bee68a5eGaurav Shahvoid Manager::InitializeProfiles() {
330d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal  DCHECK(profiles_.empty());  // The default profile must go first on stack.
331a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan  CHECK(base::CreateDirectory(storage_path_)) << storage_path_.value();
332d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal
333d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal  // Ensure that we have storage for the default profile, and that
334d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal  // the persistent copy of the default profile is not corrupt.
335870523b9e568c2b1a906426570cbc65e5149c858Paul Stewart  scoped_refptr<DefaultProfile>
336870523b9e568c2b1a906426570cbc65e5149c858Paul Stewart      default_profile(new DefaultProfile(control_interface_,
3375133b71eaa00535739ebbddd8a8f31cd8fcf33a8Thieu Le                                         metrics_,
338713547627a2d6dc731cc1a7c80d2df79bee68a5eGaurav Shah                                         this,
339713547627a2d6dc731cc1a7c80d2df79bee68a5eGaurav Shah                                         storage_path_,
340d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                                         DefaultProfile::kDefaultId,
341713547627a2d6dc731cc1a7c80d2df79bee68a5eGaurav Shah                                         props_));
3425133b71eaa00535739ebbddd8a8f31cd8fcf33a8Thieu Le  // The default profile may fail to initialize if it's corrupted.
3435133b71eaa00535739ebbddd8a8f31cd8fcf33a8Thieu Le  // If so, recreate the default profile.
344c80c460b90378124cc945b0b1f619d86949000a7mukesh agrawal  if (!default_profile->InitStorage(Profile::kCreateOrOpenExisting, nullptr))
345c80c460b90378124cc945b0b1f619d86949000a7mukesh agrawal    CHECK(default_profile->InitStorage(Profile::kCreateNew, nullptr));
34600752534b439078333ce6cefe23cbef3467d1b51mukesh agrawal  // In case we created a new profile, initialize its default values,
34700752534b439078333ce6cefe23cbef3467d1b51mukesh agrawal  // and then save. This is required for properties such as
34800752534b439078333ce6cefe23cbef3467d1b51mukesh agrawal  // PortalDetector::kDefaultCheckPortalList to be initialized correctly.
34900752534b439078333ce6cefe23cbef3467d1b51mukesh agrawal  LoadProperties(default_profile);
350d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal  default_profile->Save();
351cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan  default_profile = nullptr;  // PushProfileInternal will re-create.
352d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal
353d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal  // Read list of user profiles. This must be done before pushing the
354d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal  // default profile, because modifying the profile stack updates the
355d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal  // user profile list.
356d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal  vector<Profile::Identifier> identifiers =
357d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal      Profile::LoadUserProfileList(user_profile_list_path_);
358d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal
359d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal  // Push the default profile onto the stack.
360713547627a2d6dc731cc1a7c80d2df79bee68a5eGaurav Shah  Error error;
36119c871da666a307fdf4e5bced0d745abefe9a04aPaul Stewart  string path;
362d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal  Profile::Identifier default_profile_id;
363d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal  CHECK(Profile::ParseIdentifier(
364d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal      DefaultProfile::kDefaultId, &default_profile_id));
365d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal  PushProfileInternal(default_profile_id, &path, &error);
36692496a43b023b912f7f251d0167be360b3335690mukesh agrawal  CHECK(!profiles_.empty());  // Must have a default profile.
367d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal
368d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal  // Push user profiles onto the stack.
3698ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& profile_id : identifiers)  {
370d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal    PushProfileInternal(profile_id, &path, &error);
37178af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart  }
372713547627a2d6dc731cc1a7c80d2df79bee68a5eGaurav Shah}
373713547627a2d6dc731cc1a7c80d2df79bee68a5eGaurav Shah
3748ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::CreateProfile(const string& name, string* path, Error* error) {
375c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << __func__ << " " << name;
3765dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  Profile::Identifier ident;
3775dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  if (!Profile::ParseIdentifier(name, &ident)) {
37834f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
379be005174bce39ddad185c2eb6808117484d522adPaul Stewart                          "Invalid profile name " + name);
3805dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart    return;
3815dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  }
382d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart
383f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart  if (HasProfile(ident)) {
38434f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kAlreadyExists,
385f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart                          "Profile name " + name + " is already on stack");
386f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart    return;
387fc9a1da93210ff11eb9895430e9cc60d3e4b4a53Paul Stewart  }
388fc9a1da93210ff11eb9895430e9cc60d3e4b4a53Paul Stewart
389d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart  ProfileRefPtr profile;
390d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart  if (ident.user.empty()) {
391d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    profile = new DefaultProfile(control_interface_,
3925133b71eaa00535739ebbddd8a8f31cd8fcf33a8Thieu Le                                 metrics_,
393d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                                 this,
394d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                                 storage_path_,
395d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                                 ident.identifier,
396d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                                 props_);
397d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart  } else {
398d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    profile = new Profile(control_interface_,
3995133b71eaa00535739ebbddd8a8f31cd8fcf33a8Thieu Le                          metrics_,
400d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                          this,
401d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                          ident,
4020a59a5a484634f798222ad077dbbfa7faa76651dmukesh agrawal                          user_storage_path_,
403b672d35b6193a3e5c045af3c3a58cb027d825cb4Gary Morain                          true);
404d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart  }
405d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart
406c80c460b90378124cc945b0b1f619d86949000a7mukesh agrawal  if (!profile->InitStorage(Profile::kCreateNew, error)) {
40719c871da666a307fdf4e5bced0d745abefe9a04aPaul Stewart    // |error| will have been populated by InitStorage().
4085dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart    return;
4095dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  }
4105dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart
4115dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  // Save profile data out, and then let the scoped pointer fall out of scope.
4125dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  if (!profile->Save()) {
41334f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError,
414be005174bce39ddad185c2eb6808117484d522adPaul Stewart                          "Profile name " + name + " could not be saved");
4155dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart    return;
4165dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  }
41719c871da666a307fdf4e5bced0d745abefe9a04aPaul Stewart
41819c871da666a307fdf4e5bced0d745abefe9a04aPaul Stewart  *path = profile->GetRpcIdentifier();
4195dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart}
4205dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart
4218ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::HasProfile(const Profile::Identifier& ident) {
4228ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& profile : profiles_) {
4236db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (profile->MatchesIdentifier(ident)) {
424f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart      return true;
4255dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart    }
4265dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  }
427f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart  return false;
428f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart}
429f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart
430f3eced90466010ac4b067a565ba371c476e6de67Paul Stewartvoid Manager::PushProfileInternal(
4318ae18741780300de3126826b72593391f2d00313Paul Stewart    const Profile::Identifier& ident, string* path, Error* error) {
432f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart  if (HasProfile(ident)) {
43334f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kAlreadyExists,
434f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart                          "Profile name " + Profile::IdentifierToString(ident) +
435f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart                          " is already on stack");
436f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart    return;
437f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart  }
4385dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart
439d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart  ProfileRefPtr profile;
4405dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  if (ident.user.empty()) {
441d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    // Allow a machine-wide-profile to be pushed on the stack only if the
442d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    // profile stack is empty, or if the topmost profile on the stack is
443d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    // also a machine-wide (non-user) profile.
444d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    if (!profiles_.empty() && !profiles_.back()->GetUser().empty()) {
44534f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart      Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
446f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart                            "Cannot load non-default global profile " +
447f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart                            Profile::IdentifierToString(ident) +
448d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                            " on top of a user profile");
449d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart      return;
450d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    }
4515dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart
452d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    scoped_refptr<DefaultProfile>
453d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart        default_profile(new DefaultProfile(control_interface_,
4545133b71eaa00535739ebbddd8a8f31cd8fcf33a8Thieu Le                                           metrics_,
455d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                                           this,
456d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                                           storage_path_,
457d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                                           ident.identifier,
458d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                                           props_));
459c80c460b90378124cc945b0b1f619d86949000a7mukesh agrawal    if (!default_profile->InitStorage(Profile::kOpenExisting, nullptr)) {
46092496a43b023b912f7f251d0167be360b3335690mukesh agrawal      LOG(ERROR) << "Failed to open default profile.";
46192496a43b023b912f7f251d0167be360b3335690mukesh agrawal      // Try to continue anyway, so that we can be useful in cases
46292496a43b023b912f7f251d0167be360b3335690mukesh agrawal      // where the disk is full.
46392496a43b023b912f7f251d0167be360b3335690mukesh agrawal      default_profile->InitStubStorage();
464d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    }
465d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart
46692496a43b023b912f7f251d0167be360b3335690mukesh agrawal    LoadProperties(default_profile);
467d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    profile = default_profile;
468d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart  } else {
469d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    profile = new Profile(control_interface_,
4705133b71eaa00535739ebbddd8a8f31cd8fcf33a8Thieu Le                          metrics_,
471d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                          this,
472d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                          ident,
4730a59a5a484634f798222ad077dbbfa7faa76651dmukesh agrawal                          user_storage_path_,
474d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart                          connect_profiles_to_rpc_);
475c80c460b90378124cc945b0b1f619d86949000a7mukesh agrawal    if (!profile->InitStorage(Profile::kOpenExisting, error)) {
476d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart      // |error| will have been populated by InitStorage().
477d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart      return;
478d0a3b812f68e3c3f2e1739c2bb32ad305edc121cPaul Stewart    }
4795dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  }
4805dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart
481a849a3d95bb67e457149fbc34c49d03bdcdc7370Paul Stewart  profiles_.push_back(profile);
4825dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart
4838ae18741780300de3126826b72593391f2d00313Paul Stewart  for (ServiceRefPtr& service : services_) {
4842eee613868307d04f9e5a0efbc8c72a7ffcd90bbPaul Stewart    service->ClearExplicitlyDisconnected();
4852eee613868307d04f9e5a0efbc8c72a7ffcd90bbPaul Stewart
4862eee613868307d04f9e5a0efbc8c72a7ffcd90bbPaul Stewart    // Offer each registered Service the opportunity to join this new Profile.
487e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal    if (profile->ConfigureService(service)) {
488e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal      LOG(INFO) << "(Re-)configured service " << service->unique_name()
489e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal                << " from new profile.";
490e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal    }
4915dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  }
4925dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart
4933c5040174273386868cc8dea8044d22c465885d8Paul Stewart  // Shop the Profile contents around to Devices which may have configuration
4943c5040174273386868cc8dea8044d22c465885d8Paul Stewart  // stored in these profiles.
4958ae18741780300de3126826b72593391f2d00313Paul Stewart  for (DeviceRefPtr& device : devices_) {
496e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal    profile->ConfigureDevice(device);
497a41e38d57e4fa37bd2c8de6447890b4e1951acb7Paul Stewart  }
4983d9bcf58bd29080b96db4a2c9e7bfe6ed3d6e6dfPaul Stewart
499b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart  // Offer the Profile contents to the service providers which will
500c63dcf0b428ea99e8a9a88bc964a51e65b6dddf0Darin Petkov  // create new services if necessary.
5018ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& provider_mapping : providers_) {
502b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart    provider_mapping.second->CreateServicesFromProfile(profile);
503b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart  }
5046681533daa896254189d1061ede8aab242a82ab9Paul Stewart
50519c871da666a307fdf4e5bced0d745abefe9a04aPaul Stewart  *path = profile->GetRpcIdentifier();
5063d9bcf58bd29080b96db4a2c9e7bfe6ed3d6e6dfPaul Stewart  SortServices();
50778af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart  OnProfilesChanged();
508b94adde243da6d8f6f460c95834fbfd93219054fmukesh agrawal  LOG(INFO) << __func__ << " finished; " << profiles_.size()
509b94adde243da6d8f6f460c95834fbfd93219054fmukesh agrawal            << " profile(s) now present.";
5105dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart}
5115dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart
5128ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::PushProfile(const string& name, string* path, Error* error) {
513c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << __func__ << " " << name;
514f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart  Profile::Identifier ident;
515f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart  if (!Profile::ParseIdentifier(name, &ident)) {
51634f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
517f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart                          "Invalid profile name " + name);
518f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart    return;
519f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart  }
520f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart  PushProfileInternal(ident, path, error);
521f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart}
522f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart
5238ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::InsertUserProfile(const string& name,
5248ae18741780300de3126826b72593391f2d00313Paul Stewart                                const string& user_hash,
5258ae18741780300de3126826b72593391f2d00313Paul Stewart                                string* path,
5268ae18741780300de3126826b72593391f2d00313Paul Stewart                                Error* error) {
527c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << __func__ << " " << name;
528f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart  Profile::Identifier ident;
529f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart  if (!Profile::ParseIdentifier(name, &ident) ||
530f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart      ident.user.empty()) {
53134f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
532f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart                          "Invalid user profile name " + name);
533f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart    return;
534f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart  }
535f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart  ident.user_hash = user_hash;
536f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart  PushProfileInternal(ident, path, error);
537f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart}
538f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart
5395dc40aad05908dc435e623e56392780ef6d1079ePaul Stewartvoid Manager::PopProfileInternal() {
5405dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  CHECK(!profiles_.empty());
5415dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  ProfileRefPtr active_profile = profiles_.back();
5425dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  profiles_.pop_back();
543e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal  for (auto it = services_.begin(); it != services_.end();) {
5442eee613868307d04f9e5a0efbc8c72a7ffcd90bbPaul Stewart    (*it)->ClearExplicitlyDisconnected();
545e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal    if (IsServiceEphemeral(*it)) {
546e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal      // Not affected, since the EphemeralProfile isn't on the stack.
547e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal      // Not logged, since ephemeral services aren't that interesting.
548e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal      ++it;
549e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal      continue;
550e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal    }
551e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal
552e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal    if ((*it)->profile().get() != active_profile.get()) {
553e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal      LOG(INFO) << "Skipping unload of service " << (*it)->unique_name()
554e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal                << ": wasn't using this profile.";
55565512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart      ++it;
556e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal      continue;
5575dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart    }
558e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal
559e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal    if (MatchProfileWithService(*it)) {
560e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal      LOG(INFO) << "Skipping unload of service " << (*it)->unique_name()
561e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal                << ": re-configured from another profile.";
562e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal      ++it;
563e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal      continue;
564e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal    }
565e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal
566e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal    if (!UnloadService(&it)) {
567e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal      LOG(INFO) << "Service " << (*it)->unique_name()
568ca9ddaea72127a572b375c79d437fccd45ea2e0dPaul Stewart                << " not completely unloaded.";
569e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal      ++it;
570e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal      continue;
571e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal    }
572e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal
573e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal    // Service was totally unloaded. No advance of iterator in this
574e28e1e513f8c2977aa31f27ecde5e89671610085mukesh agrawal    // case, as UnloadService has updated the iterator for us.
5755dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  }
5763d9bcf58bd29080b96db4a2c9e7bfe6ed3d6e6dfPaul Stewart  SortServices();
57778af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart  OnProfilesChanged();
578b94adde243da6d8f6f460c95834fbfd93219054fmukesh agrawal  LOG(INFO) << __func__ << " finished; " << profiles_.size()
579b94adde243da6d8f6f460c95834fbfd93219054fmukesh agrawal            << " profile(s) still present.";
58078af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart}
5817917360b71c6680de60b487b3630dc1a0f8cdca2Philipp Neubeck
58278af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewartvoid Manager::OnProfilesChanged() {
5837917360b71c6680de60b487b3630dc1a0f8cdca2Philipp Neubeck  Error unused_error;
58478af94ce5ff7c3f22bda6148c6115ec8591129a5Paul Stewart
585923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  adaptor_->EmitStringsChanged(kProfilesProperty,
5867917360b71c6680de60b487b3630dc1a0f8cdca2Philipp Neubeck                               EnumerateProfiles(&unused_error));
587d142fd64e818027815377f5b7d2fc4679db08aa5mukesh agrawal  Profile::SaveUserProfileList(user_profile_list_path_, profiles_);
5885dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart}
5895dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart
5908ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::PopProfile(const string& name, Error* error) {
591c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << __func__ << " " << name;
5925dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  Profile::Identifier ident;
5935dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  if (profiles_.empty()) {
59434f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(
59534f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart        FROM_HERE, error, Error::kNotFound, "Profile stack is empty");
5965dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart    return;
5975dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  }
5985dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  ProfileRefPtr active_profile = profiles_.back();
5995dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  if (!Profile::ParseIdentifier(name, &ident)) {
60034f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
601be005174bce39ddad185c2eb6808117484d522adPaul Stewart                          "Invalid profile name " + name);
6025dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart    return;
6035dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  }
6045dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  if (!active_profile->MatchesIdentifier(ident)) {
60534f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
606be005174bce39ddad185c2eb6808117484d522adPaul Stewart                          name + " is not the active profile");
6075dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart    return;
6085dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  }
6095dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  PopProfileInternal();
6105dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart}
6115dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart
6128ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::PopAnyProfile(Error* error) {
613c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << __func__;
6145dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  Profile::Identifier ident;
6155dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  if (profiles_.empty()) {
61634f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(
61734f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart        FROM_HERE, error, Error::kNotFound, "Profile stack is empty");
6185dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart    return;
6195dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  }
6205dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart  PopProfileInternal();
6215dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart}
6225dc40aad05908dc435e623e56392780ef6d1079ePaul Stewart
6238ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::PopAllUserProfiles(Error* /*error*/) {
624c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << __func__;
625307c250b76de403ac086279fe67964c59daa4cddPaul Stewart  while (!profiles_.empty() && !profiles_.back()->GetUser().empty()) {
626307c250b76de403ac086279fe67964c59daa4cddPaul Stewart    PopProfileInternal();
627307c250b76de403ac086279fe67964c59daa4cddPaul Stewart  }
628307c250b76de403ac086279fe67964c59daa4cddPaul Stewart}
629307c250b76de403ac086279fe67964c59daa4cddPaul Stewart
6308ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::RemoveProfile(const string& name, Error* error) {
631e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart  Profile::Identifier ident;
632e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart  if (!Profile::ParseIdentifier(name, &ident)) {
63334f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
634e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart                          "Invalid profile name " + name);
635e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart    return;
636e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart  }
637e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart
638f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart  if (HasProfile(ident)) {
63934f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
640f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart                          "Cannot remove profile name " + name +
641f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart                          " since it is on stack");
642f3eced90466010ac4b067a565ba371c476e6de67Paul Stewart    return;
643e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart  }
644e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart
645e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart  ProfileRefPtr profile;
646e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart  if (ident.user.empty()) {
647e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart    profile = new DefaultProfile(control_interface_,
6485133b71eaa00535739ebbddd8a8f31cd8fcf33a8Thieu Le                                 metrics_,
649e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart                                 this,
650e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart                                 storage_path_,
651e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart                                 ident.identifier,
652e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart                                 props_);
653e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart  } else {
654e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart    profile = new Profile(control_interface_,
6555133b71eaa00535739ebbddd8a8f31cd8fcf33a8Thieu Le                          metrics_,
656e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart                          this,
657e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart                          ident,
6580a59a5a484634f798222ad077dbbfa7faa76651dmukesh agrawal                          user_storage_path_,
659e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart                          false);
660e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart  }
661e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart
662e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart
663e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart  // |error| will have been populated if RemoveStorage fails.
664c80c460b90378124cc945b0b1f619d86949000a7mukesh agrawal  profile->RemoveStorage(error);
665e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart
666e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart  return;
667e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart}
668e73d05ca690cc847f512072f4709c92cbd7b0651Paul Stewart
669c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grantbool Manager::DeviceManagementAllowed(const string& device_name) {
670c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant  if (std::find(blacklisted_devices_.begin(),
671c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant                blacklisted_devices_.end(),
672c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant                device_name) != blacklisted_devices_.end()) {
673c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant    return false;
674c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant  }
675c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant  if (!whitelisted_devices_.size()) {
676c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant    // If no whitelist is specified, all devices are considered whitelisted.
677c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant    return true;
678c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant  }
679c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant  if (std::find(whitelisted_devices_.begin(),
680c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant                whitelisted_devices_.end(),
681c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant                device_name) != whitelisted_devices_.end()) {
682c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant    return true;
683c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant  }
684c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant  return false;
685c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant}
686c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant
6878ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::ClaimDevice(const string& claimer_name,
6888ae18741780300de3126826b72593391f2d00313Paul Stewart                          const string& device_name,
689c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu                          Error* error) {
6907e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  SLOG(this, 2) << __func__;
6917e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu
6927e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  // Basic check for device name.
6937e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  if (device_name.empty()) {
69434f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
6957e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu                          "Empty device name");
6967e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu    return;
6977e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  }
6987e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu
699c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant  if (!DeviceManagementAllowed(device_name)) {
70091b7150819b785f36c2c094ae4aa102336bd6f71Peter Qiu    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
701c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant                          "Not allowed to claim unmanaged device");
70291b7150819b785f36c2c094ae4aa102336bd6f71Peter Qiu    return;
70391b7150819b785f36c2c094ae4aa102336bd6f71Peter Qiu  }
70491b7150819b785f36c2c094ae4aa102336bd6f71Peter Qiu
705c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu  // Verify default claimer.
706c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu  if (claimer_name.empty() &&
707c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu      (!device_claimer_ || !device_claimer_->default_claimer())) {
708c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
709c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu                          "No default claimer");
710c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu    return;
711c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu  }
712c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu
7137e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  // Create a new device claimer if one doesn't exist yet.
7147e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  if (!device_claimer_) {
715c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu    // Start a device claimer.  No need to verify the existence of the claimer,
716c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu    // since we are using message sender as the claimer name.
7171d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu    device_claimer_.reset(
7181d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu        new DeviceClaimer(claimer_name, &device_info_, false));
7197e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  }
7207e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu
7217e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  // Verify claimer's name, since we only allow one claimer to exist at a time.
7227e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  if (device_claimer_->name() != claimer_name) {
72334f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
7247e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu                          "Invalid claimer name " + claimer_name +
7257e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu                          ". Claimer " + device_claimer_->name() +
7267e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu                          " already exist");
7277e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu    return;
7287e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  }
7297e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu
7307e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  // Error will be populated by the claimer if failed to claim the device.
7317e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  if (!device_claimer_->Claim(device_name, error)) {
7327e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu    return;
7337e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  }
7347e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu
7357e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  // Deregister the device from manager if it is registered.
7367e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  DeregisterDeviceByLinkName(device_name);
7377e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu}
7387e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu
7398ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::ReleaseDevice(const string& claimer_name,
7408ae18741780300de3126826b72593391f2d00313Paul Stewart                            const string& device_name,
7418a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan                            bool* claimer_removed,
7428ae18741780300de3126826b72593391f2d00313Paul Stewart                            Error* error) {
7437e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  SLOG(this, 2) << __func__;
74491b7150819b785f36c2c094ae4aa102336bd6f71Peter Qiu
7458a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan  *claimer_removed = false;
7468a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan
747c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant  if (!DeviceManagementAllowed(device_name)) {
74891b7150819b785f36c2c094ae4aa102336bd6f71Peter Qiu    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
749c1d447354db29b83262c7db0857baa84e05e0c2aChristopher Grant                          "Not allowed to release unmanaged device");
75091b7150819b785f36c2c094ae4aa102336bd6f71Peter Qiu    return;
75191b7150819b785f36c2c094ae4aa102336bd6f71Peter Qiu  }
75291b7150819b785f36c2c094ae4aa102336bd6f71Peter Qiu
7537e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  if (!device_claimer_) {
75434f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
7557e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu                          "Device claimer doesn't exist");
7567e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu    return;
7577e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  }
7581d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu
7591d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  // Verify claimer's name, since we only allow one claimer to exist at a time.
7601d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  if (device_claimer_->name() != claimer_name) {
7611d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
7621d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu                          "Invalid claimer name " + claimer_name +
7631d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu                          ". Claimer " + device_claimer_->name() +
7641d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu                          " already exist");
7651d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu    return;
7661d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  }
7671d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu
7687e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  // Release the device from the claimer. Error should be populated by the
7697e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  // claimer if it failed to release the given device.
7707e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  device_claimer_->Release(device_name, error);
7717e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu
7721d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  // Reset claimer if this is not the default claimer and no more devices are
7731d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  // claimed by this claimer.
7741d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  if (!device_claimer_->default_claimer() &&
7751d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu      !device_claimer_->DevicesClaimed()) {
7767e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu    device_claimer_.reset();
7778a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan    *claimer_removed = true;
7787e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  }
7797e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu}
7807e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu
781d13249c35eb0c5281c422a3c17a252b5cc8c865dPeter Qiu#if !defined(DISABLE_WIFI) && defined(__BRILLO__)
7828a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tanbool Manager::SetupApModeInterface(string* out_interface_name, Error* error) {
783d13249c35eb0c5281c422a3c17a252b5cc8c865dPeter Qiu  string interface_name = wifi_driver_hal_->SetupApModeInterface();
78495522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu  if (interface_name.empty()) {
78595522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu    Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed,
78695522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu                          "Failed to setup AP mode interface");
78795522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu    return false;
78895522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu  }
78995522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu  *out_interface_name = interface_name;
79095522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu  return true;
79195522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu}
79295522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu
79395522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiubool Manager::SetupStationModeInterface(string* out_interface_name,
79495522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu                                        Error* error) {
795d13249c35eb0c5281c422a3c17a252b5cc8c865dPeter Qiu  string interface_name = wifi_driver_hal_->SetupStationModeInterface();
79695522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu  if (interface_name.empty()) {
79795522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu    Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed,
79895522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu                          "Failed to setup station mode interface");
79995522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu    return false;
80095522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu  }
80195522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu  *out_interface_name = interface_name;
80295522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu  return true;
80395522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu}
8048a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan
8058a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tanvoid Manager::OnApModeSetterVanished() {
8068a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan  // Restore station mode interface.
8078a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan  string interface_name = wifi_driver_hal_->SetupStationModeInterface();
8088a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan  if (interface_name.empty()) {
8098a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan    LOG(ERROR) << "Failed to restore station mode interface";
8108a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan  }
8118a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan}
812d13249c35eb0c5281c422a3c17a252b5cc8c865dPeter Qiu#endif  // !DISABLE_WIFI && __BRILLO__
81395522afb22e28fdf981ac9161e4400df909ff3e3Peter Qiu
8148ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::RemoveService(const ServiceRefPtr& service) {
815d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart  LOG(INFO) << __func__ << " for service " << service->unique_name();
816d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart  if (!IsServiceEphemeral(service)) {
817d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart    service->profile()->AbandonService(service);
818d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart    if (MatchProfileWithService(service)) {
819d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart      // We found another profile to adopt the service; no need to unload.
820d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart      UpdateService(service);
821d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart      return;
822d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart    }
823d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart  }
824d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart  auto service_it = std::find(services_.begin(), services_.end(), service);
825d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart  CHECK(service_it != services_.end());
826d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart  if (!UnloadService(&service_it)) {
827d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart    UpdateService(service);
828d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart  }
829d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart  SortServices();
830d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart}
831d3d0388d4c93e0f1f526671f3826c219cf438886Paul Stewart
8328ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::HandleProfileEntryDeletion(const ProfileRefPtr& profile,
8338ae18741780300de3126826b72593391f2d00313Paul Stewart                                         const std::string& entry_name) {
8347522551440b9a287bccf2d95a42357d04ab79814Paul Stewart  bool moved_services = false;
8356db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart  for (auto it = services_.begin(); it != services_.end();) {
8367522551440b9a287bccf2d95a42357d04ab79814Paul Stewart    if ((*it)->profile().get() == profile.get() &&
8377522551440b9a287bccf2d95a42357d04ab79814Paul Stewart        (*it)->GetStorageIdentifier() == entry_name) {
8387522551440b9a287bccf2d95a42357d04ab79814Paul Stewart      profile->AbandonService(*it);
83965512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart      if (MatchProfileWithService(*it) ||
84065512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart          !UnloadService(&it)) {
84165512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart        ++it;
8427522551440b9a287bccf2d95a42357d04ab79814Paul Stewart      }
8437522551440b9a287bccf2d95a42357d04ab79814Paul Stewart      moved_services = true;
84465512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart    } else {
84565512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart      ++it;
8467522551440b9a287bccf2d95a42357d04ab79814Paul Stewart    }
8477522551440b9a287bccf2d95a42357d04ab79814Paul Stewart  }
848fbca6bc6d9ce8966680250b0c2c13fa67406ccb8Paul Stewart  if (moved_services) {
849fbca6bc6d9ce8966680250b0c2c13fa67406ccb8Paul Stewart    SortServices();
850fbca6bc6d9ce8966680250b0c2c13fa67406ccb8Paul Stewart  }
8517522551440b9a287bccf2d95a42357d04ab79814Paul Stewart  return moved_services;
8527522551440b9a287bccf2d95a42357d04ab79814Paul Stewart}
8537522551440b9a287bccf2d95a42357d04ab79814Paul Stewart
854967eaebb63aac3b9679dc4b2dca0565292e3af03Paul Stewartmap<string, string> Manager::GetLoadableProfileEntriesForService(
8558ae18741780300de3126826b72593391f2d00313Paul Stewart    const ServiceConstRefPtr& service) {
856967eaebb63aac3b9679dc4b2dca0565292e3af03Paul Stewart  map<string, string> profile_entries;
8578ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& profile : profiles_) {
858967eaebb63aac3b9679dc4b2dca0565292e3af03Paul Stewart    string entry_name = service->GetLoadableStorageIdentifier(
859967eaebb63aac3b9679dc4b2dca0565292e3af03Paul Stewart        *profile->GetConstStorage());
860967eaebb63aac3b9679dc4b2dca0565292e3af03Paul Stewart    if (!entry_name.empty()) {
861967eaebb63aac3b9679dc4b2dca0565292e3af03Paul Stewart      profile_entries[profile->GetRpcIdentifier()] = entry_name;
862967eaebb63aac3b9679dc4b2dca0565292e3af03Paul Stewart    }
863967eaebb63aac3b9679dc4b2dca0565292e3af03Paul Stewart  }
864967eaebb63aac3b9679dc4b2dca0565292e3af03Paul Stewart  return profile_entries;
865967eaebb63aac3b9679dc4b2dca0565292e3af03Paul Stewart}
866967eaebb63aac3b9679dc4b2dca0565292e3af03Paul Stewart
8670756db95c9d39d6e6aa9a754e54b441eff46ff34Paul StewartServiceRefPtr Manager::GetServiceWithStorageIdentifier(
8688ae18741780300de3126826b72593391f2d00313Paul Stewart    const ProfileRefPtr& profile, const std::string& entry_name, Error* error) {
8698ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_) {
8706db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (service->profile().get() == profile.get() &&
8716db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart        service->GetStorageIdentifier() == entry_name) {
8726db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart      return service;
8730756db95c9d39d6e6aa9a754e54b441eff46ff34Paul Stewart    }
8740756db95c9d39d6e6aa9a754e54b441eff46ff34Paul Stewart  }
8750756db95c9d39d6e6aa9a754e54b441eff46ff34Paul Stewart
87618213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu  SLOG(this, 2) << "Entry " << entry_name
87718213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu                << " is not registered in the manager";
878cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan  return nullptr;
8790756db95c9d39d6e6aa9a754e54b441eff46ff34Paul Stewart}
8800756db95c9d39d6e6aa9a754e54b441eff46ff34Paul Stewart
88118213652e2ce4c6e4354951e5b665097b7a7aa6bPeter QiuServiceRefPtr Manager::CreateTemporaryServiceFromProfile(
8828ae18741780300de3126826b72593391f2d00313Paul Stewart    const ProfileRefPtr& profile, const std::string& entry_name, Error* error) {
88318213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu  Technology::Identifier technology =
88418213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu      Technology::IdentifierFromStorageGroup(entry_name);
88518213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu  if (technology == Technology::kUnknown) {
88618213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu    Error::PopulateAndLog(
88718213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu        FROM_HERE, error, Error::kInternalError,
88818213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu        "Could not determine technology for entry: " + entry_name);
88918213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu    return nullptr;
89018213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu  }
89118213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu
8926fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu  ServiceRefPtr service = nullptr;
8936fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu  // Since there is no provider for Ethernet services (Ethernet services are
8946fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu  // created/provided by the Ethernet device), we will explicitly create
8956fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu  // temporary Ethernet services for loading Ethernet entries.
8966fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu  if (technology == Technology::kEthernet) {
8976fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu    service = new EthernetTemporaryService(control_interface_,
8986fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu                                           dispatcher_,
8996fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu                                           metrics_,
9006fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu                                           this,
9016fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu                                           entry_name);
9026fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu  } else if (ContainsKey(providers_, technology)) {
9036fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu    service =
9046fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu        providers_[technology]->CreateTemporaryServiceFromProfile(
9056fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu            profile, entry_name, error);
9066fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu  }
9076fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu
9086fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu  if (!service) {
90918213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu    Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
91018213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu                          kErrorUnsupportedServiceType);
91118213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu    return nullptr;
91218213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu  }
91318213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu
9146fc1a8c5f20dd52992a598a809d44ba8d489aad8Peter Qiu  profile->LoadService(service);
91518213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu  return service;
91618213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu}
91718213652e2ce4c6e4354951e5b665097b7a7aa6bPeter Qiu
91813ed225b4a4567e8e2411435d1266c8b86236c54Paul StewartServiceRefPtr Manager::GetServiceWithGUID(
9198ae18741780300de3126826b72593391f2d00313Paul Stewart    const std::string& guid, Error* error) {
9208ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_) {
9216db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (service->guid() == guid) {
9226db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart      return service;
92313ed225b4a4567e8e2411435d1266c8b86236c54Paul Stewart    }
92413ed225b4a4567e8e2411435d1266c8b86236c54Paul Stewart  }
92513ed225b4a4567e8e2411435d1266c8b86236c54Paul Stewart
92676a89cbcd3094d8420b64287998b15d3bf3e039bPaul Stewart  string error_string(
92713ed225b4a4567e8e2411435d1266c8b86236c54Paul Stewart      StringPrintf("Service wth GUID %s is not registered in the manager",
92813ed225b4a4567e8e2411435d1266c8b86236c54Paul Stewart                   guid.c_str()));
92976a89cbcd3094d8420b64287998b15d3bf3e039bPaul Stewart  if (error) {
93076a89cbcd3094d8420b64287998b15d3bf3e039bPaul Stewart    error->Populate(Error::kNotFound, error_string);
93176a89cbcd3094d8420b64287998b15d3bf3e039bPaul Stewart  }
932c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << error_string;
933cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan  return nullptr;
93413ed225b4a4567e8e2411435d1266c8b86236c54Paul Stewart}
93513ed225b4a4567e8e2411435d1266c8b86236c54Paul Stewart
936e2bad7c1edd7dbe837619e5350bd70814e6913bePaul StewartServiceRefPtr Manager::GetDefaultService() const {
937c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << __func__;
938e2bad7c1edd7dbe837619e5350bd70814e6913bePaul Stewart  if (services_.empty() || !services_[0]->connection().get()) {
939c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein    SLOG(this, 2) << "In " << __func__ << ": No default connection exists.";
940cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan    return nullptr;
941e2bad7c1edd7dbe837619e5350bd70814e6913bePaul Stewart  }
942e2bad7c1edd7dbe837619e5350bd70814e6913bePaul Stewart  return services_[0];
943e2bad7c1edd7dbe837619e5350bd70814e6913bePaul Stewart}
944e2bad7c1edd7dbe837619e5350bd70814e6913bePaul Stewart
9458ae18741780300de3126826b72593391f2d00313Paul StewartRpcIdentifier Manager::GetDefaultServiceRpcIdentifier(Error* /*error*/) {
94649739c08a76187fae6494c61e960eec315960715Paul Stewart  ServiceRefPtr default_service = GetDefaultService();
947c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu  return default_service ? default_service->GetRpcIdentifier() :
948c00d1fa87127a33bd1e1a7cf049a54a9cca49d68Peter Qiu      control_interface_->NullRPCIdentifier();
94949739c08a76187fae6494c61e960eec315960715Paul Stewart}
95049739c08a76187fae6494c61e960eec315960715Paul Stewart
9518ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::IsTechnologyInList(const string& technology_list,
952036dba0c6641acdbe02d52260c6fa6dca84b1af2Paul Stewart                                 Technology::Identifier tech) const {
9538e6b8ef22e185310480c13aa3a6e89184cce62d1Ben Chan  if (technology_list.empty())
9548e6b8ef22e185310480c13aa3a6e89184cce62d1Ben Chan    return false;
9558e6b8ef22e185310480c13aa3a6e89184cce62d1Ben Chan
95620088d860631a67c151a12783fbbee63c708792fPaul Stewart  Error error;
957036dba0c6641acdbe02d52260c6fa6dca84b1af2Paul Stewart  vector<Technology::Identifier> technologies;
958036dba0c6641acdbe02d52260c6fa6dca84b1af2Paul Stewart  return Technology::GetTechnologyVectorFromString(technology_list,
959036dba0c6641acdbe02d52260c6fa6dca84b1af2Paul Stewart                                                   &technologies,
96020088d860631a67c151a12783fbbee63c708792fPaul Stewart                                                   &error) &&
961036dba0c6641acdbe02d52260c6fa6dca84b1af2Paul Stewart      std::find(technologies.begin(), technologies.end(), tech) !=
962036dba0c6641acdbe02d52260c6fa6dca84b1af2Paul Stewart          technologies.end();
963036dba0c6641acdbe02d52260c6fa6dca84b1af2Paul Stewart}
964036dba0c6641acdbe02d52260c6fa6dca84b1af2Paul Stewart
965036dba0c6641acdbe02d52260c6fa6dca84b1af2Paul Stewartbool Manager::IsPortalDetectionEnabled(Technology::Identifier tech) {
966cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan  return IsTechnologyInList(GetCheckPortalList(nullptr), tech);
96720088d860631a67c151a12783fbbee63c708792fPaul Stewart}
96820088d860631a67c151a12783fbbee63c708792fPaul Stewart
9698ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::SetStartupPortalList(const string& portal_list) {
97010e9e4e93537a0673524d47535cbf0f723470a0dPaul Stewart  startup_portal_list_ = portal_list;
97110e9e4e93537a0673524d47535cbf0f723470a0dPaul Stewart  use_startup_portal_list_ = true;
97210e9e4e93537a0673524d47535cbf0f723470a0dPaul Stewart}
97310e9e4e93537a0673524d47535cbf0f723470a0dPaul Stewart
9748ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::IsProfileBefore(const ProfileRefPtr& a,
9758ae18741780300de3126826b72593391f2d00313Paul Stewart                              const ProfileRefPtr& b) const {
976d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  DCHECK(a != b);
9778ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& profile : profiles_) {
9786db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (profile == a) {
979d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart      return true;
980d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart    }
9816db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (profile == b) {
982d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart      return false;
983d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart    }
984d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  }
985d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  NOTREACHED() << "We should have found both profiles in the profiles_ list!";
986d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  return false;
987d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart}
988d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart
9898ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::IsServiceEphemeral(const ServiceConstRefPtr& service) const {
99010ccbb3c6bc4f4246105743c8508fc9ce8759c17Paul Stewart  return service->profile() == ephemeral_profile_;
99110ccbb3c6bc4f4246105743c8508fc9ce8759c17Paul Stewart}
99210ccbb3c6bc4f4246105743c8508fc9ce8759c17Paul Stewart
993036dba0c6641acdbe02d52260c6fa6dca84b1af2Paul Stewartbool Manager::IsTechnologyLinkMonitorEnabled(
994036dba0c6641acdbe02d52260c6fa6dca84b1af2Paul Stewart    Technology::Identifier technology) const {
995036dba0c6641acdbe02d52260c6fa6dca84b1af2Paul Stewart  return IsTechnologyInList(props_.link_monitor_technologies, technology);
996bf667617d573e3af4b808ed317b1d6ca04747ee4Paul Stewart}
997bf667617d573e3af4b808ed317b1d6ca04747ee4Paul Stewart
9988e6b8ef22e185310480c13aa3a6e89184cce62d1Ben Chanbool Manager::IsTechnologyAutoConnectDisabled(
9998e6b8ef22e185310480c13aa3a6e89184cce62d1Ben Chan    Technology::Identifier technology) const {
10008e6b8ef22e185310480c13aa3a6e89184cce62d1Ben Chan  return IsTechnologyInList(props_.no_auto_connect_technologies, technology);
10018e6b8ef22e185310480c13aa3a6e89184cce62d1Ben Chan}
10028e6b8ef22e185310480c13aa3a6e89184cce62d1Ben Chan
1003ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewartbool Manager::IsTechnologyProhibited(
1004ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart    Technology::Identifier technology) const {
1005ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  return IsTechnologyInList(props_.prohibited_technologies, technology);
1006ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart}
1007ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart
10088ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::OnProfileStorageInitialized(Profile* profile) {
10091a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIFI)
10109842441bbfae81053a6c08045f1d7b831e5101b2mukesh agrawal  wifi_provider_->LoadAndFixupServiceEntries(profile);
10111a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif  // DISABLE_WIFI
10123c5040174273386868cc8dea8044d22c465885d8Paul Stewart}
10133c5040174273386868cc8dea8044d22c465885d8Paul Stewart
10143c5040174273386868cc8dea8044d22c465885d8Paul StewartDeviceRefPtr Manager::GetEnabledDeviceWithTechnology(
10153c5040174273386868cc8dea8044d22c465885d8Paul Stewart    Technology::Identifier technology) const {
10168ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : FilterByTechnology(technology)) {
10176db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (device->enabled()) {
10186db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart      return device;
1019a900f4a4b94d852e2a52a59f59ede4261d48ad80Peter Qiu    }
1020a900f4a4b94d852e2a52a59f59ede4261d48ad80Peter Qiu  }
1021a900f4a4b94d852e2a52a59f59ede4261d48ad80Peter Qiu  return nullptr;
1022a900f4a4b94d852e2a52a59f59ede4261d48ad80Peter Qiu}
1023a900f4a4b94d852e2a52a59f59ede4261d48ad80Peter Qiu
1024a900f4a4b94d852e2a52a59f59ede4261d48ad80Peter QiuDeviceRefPtr Manager::GetEnabledDeviceByLinkName(
10258ae18741780300de3126826b72593391f2d00313Paul Stewart    const string& link_name) const {
1026a900f4a4b94d852e2a52a59f59ede4261d48ad80Peter Qiu  for (const auto& device : devices_) {
1027a900f4a4b94d852e2a52a59f59ede4261d48ad80Peter Qiu    if (device->link_name() == link_name) {
1028a900f4a4b94d852e2a52a59f59ede4261d48ad80Peter Qiu      if (!device->enabled()) {
1029a900f4a4b94d852e2a52a59f59ede4261d48ad80Peter Qiu        return nullptr;
1030a900f4a4b94d852e2a52a59f59ede4261d48ad80Peter Qiu      }
1031a900f4a4b94d852e2a52a59f59ede4261d48ad80Peter Qiu      return device;
10323c5040174273386868cc8dea8044d22c465885d8Paul Stewart    }
103385aea151c69ff40967becfa8751d821feebf3bb9Paul Stewart  }
1034cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan  return nullptr;
103585aea151c69ff40967becfa8751d821feebf3bb9Paul Stewart}
103685aea151c69ff40967becfa8751d821feebf3bb9Paul Stewart
10378ae18741780300de3126826b72593391f2d00313Paul Stewartconst ProfileRefPtr& Manager::ActiveProfile() const {
1038c74cf9cb439ef518bc00210fe5cd3b121f3079b3Eric Shienbrood  DCHECK_NE(profiles_.size(), 0U);
10397aa5f90848b530999d8b6788ecb40aa30871c7aeChris Masone  return profiles_.back();
10407aa5f90848b530999d8b6788ecb40aa30871c7aeChris Masone}
10417aa5f90848b530999d8b6788ecb40aa30871c7aeChris Masone
10428ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::IsActiveProfile(const ProfileRefPtr& profile) const {
10431b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart  return (profiles_.size() > 0 &&
10441b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart          ActiveProfile().get() == profile.get());
10451b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart}
10461b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart
10478ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::MoveServiceToProfile(const ServiceRefPtr& to_move,
10488ae18741780300de3126826b72593391f2d00313Paul Stewart                                   const ProfileRefPtr& destination) {
10496515aabcd1fbbb9ff2090c9675c17eeef64e7474Chris Masone  const ProfileRefPtr from = to_move->profile();
1050c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << "Moving service "
1051c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                << to_move->unique_name()
1052c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                << " to profile "
1053c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                << destination->GetFriendlyName()
1054c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                << " from "
1055c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                << from->GetFriendlyName();
1056457728b3eeb2d67c980e0d20675f0a0f750903e1Darin Petkov  return destination->AdoptService(to_move) && from->AbandonService(to_move);
10576791a43add38926966bd420e89541717fb2cb2b5Chris Masone}
10586791a43add38926966bd420e89541717fb2cb2b5Chris Masone
10597f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul StewartProfileRefPtr Manager::LookupProfileByRpcIdentifier(
10608ae18741780300de3126826b72593391f2d00313Paul Stewart    const string& profile_rpcid) {
10618ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& profile : profiles_) {
10626db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (profile_rpcid == profile->GetRpcIdentifier()) {
10636db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart      return profile;
10641b1a7f222bc8a2b6c9f15fd7a41aad7977ff275ePaul Stewart    }
10651b1a7f222bc8a2b6c9f15fd7a41aad7977ff275ePaul Stewart  }
1066cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan  return nullptr;
10677f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart}
10687f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart
10698ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::SetProfileForService(const ServiceRefPtr& to_set,
10708ae18741780300de3126826b72593391f2d00313Paul Stewart                                   const string& profile_rpcid,
10718ae18741780300de3126826b72593391f2d00313Paul Stewart                                   Error* error) {
10727f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  ProfileRefPtr profile = LookupProfileByRpcIdentifier(profile_rpcid);
10737f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  if (!profile) {
107434f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
10757f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart                          StringPrintf("Unknown Profile %s requested for "
10767f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart                                       "Service", profile_rpcid.c_str()));
10777f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart    return;
10787f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  }
10797f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart
1080649f3a4c7328952ac018f567fedbc330340d13a3Paul Stewart  if (!to_set->profile()) {
1081649f3a4c7328952ac018f567fedbc330340d13a3Paul Stewart    // We are being asked to set the profile property of a service that
1082649f3a4c7328952ac018f567fedbc330340d13a3Paul Stewart    // has never been registered.  Now is a good time to register it.
1083649f3a4c7328952ac018f567fedbc330340d13a3Paul Stewart    RegisterService(to_set);
1084649f3a4c7328952ac018f567fedbc330340d13a3Paul Stewart  }
1085649f3a4c7328952ac018f567fedbc330340d13a3Paul Stewart
10867f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  if (to_set->profile().get() == profile.get()) {
108734f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
10887f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart                          "Service is already connected to this profile");
10897f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  } else if (!MoveServiceToProfile(to_set, profile)) {
109034f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError,
10917f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart                          "Unable to move service to profile");
10927f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  }
10931b1a7f222bc8a2b6c9f15fd7a41aad7977ff275ePaul Stewart}
10941b1a7f222bc8a2b6c9f15fd7a41aad7977ff275ePaul Stewart
10958ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::SetEnabledStateForTechnology(const std::string& technology_name,
109646c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal                                           bool enabled_state,
1097b0d2f64a672a970a7dc1f846c36c0cd411177662Rebecca Silberstein                                           bool persist,
10988ae18741780300de3126826b72593391f2d00313Paul Stewart                                           Error* error,
10998ae18741780300de3126826b72593391f2d00313Paul Stewart                                           const ResultCallback& callback) {
1100cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan  CHECK(error);
1101df7c553368620f718ec14bc6751f232185792870Jason Glasgow  DCHECK(error->IsOngoing());
11029a24553461df7036755060423f90804011612249Eric Shienbrood  Technology::Identifier id = Technology::IdentifierFromName(technology_name);
11039a24553461df7036755060423f90804011612249Eric Shienbrood  if (id == Technology::kUnknown) {
11049a24553461df7036755060423f90804011612249Eric Shienbrood    error->Populate(Error::kInvalidArguments, "Unknown technology");
11059a24553461df7036755060423f90804011612249Eric Shienbrood    return;
11069a24553461df7036755060423f90804011612249Eric Shienbrood  }
1107ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  if (enabled_state && IsTechnologyProhibited(id)) {
1108ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart    error->Populate(Error::kPermissionDenied,
1109ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart                    "The " + technology_name + " technology is prohibited");
1110ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart    return;
1111ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  }
1112df7c553368620f718ec14bc6751f232185792870Jason Glasgow  bool deferred = false;
1113b711ba242167c46e5af9b7379bbf289f41e9ad1emukesh agrawal  auto result_aggregator(make_scoped_refptr(new ResultAggregator(callback)));
11148ae18741780300de3126826b72593391f2d00313Paul Stewart  for (auto& device : devices_) {
11152f352e606bbe6074eeca93eb457837e501420be7Arman Uguray    if (device->technology() != id)
111646c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal      continue;
111746c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal
111846c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal    Error device_error(Error::kOperationInitiated);
111946c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal    ResultCallback aggregator_callback(
112046c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal        Bind(&ResultAggregator::ReportResult, result_aggregator));
1121b0d2f64a672a970a7dc1f846c36c0cd411177662Rebecca Silberstein    if (persist) {
1122b0d2f64a672a970a7dc1f846c36c0cd411177662Rebecca Silberstein      device->SetEnabledPersistent(
1123b0d2f64a672a970a7dc1f846c36c0cd411177662Rebecca Silberstein          enabled_state, &device_error, aggregator_callback);
1124b0d2f64a672a970a7dc1f846c36c0cd411177662Rebecca Silberstein    } else {
1125b0d2f64a672a970a7dc1f846c36c0cd411177662Rebecca Silberstein      device->SetEnabledNonPersistent(
1126b0d2f64a672a970a7dc1f846c36c0cd411177662Rebecca Silberstein          enabled_state, &device_error, aggregator_callback);
1127b0d2f64a672a970a7dc1f846c36c0cd411177662Rebecca Silberstein    }
112846c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal    if (device_error.IsOngoing()) {
112946c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal      deferred = true;
113046c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal    } else if (!error->IsFailure()) {  // Report first failure.
113146c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal      error->CopyFrom(device_error);
11329a24553461df7036755060423f90804011612249Eric Shienbrood    }
11339a24553461df7036755060423f90804011612249Eric Shienbrood  }
113446c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal  if (deferred) {
113546c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal    // Some device is handling this change asynchronously. Clobber any error
113646c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal    // from another device, so that we can indicate the operation is still in
113746c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal    // progress.
113846c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal    error->Populate(Error::kOperationInitiated);
113946c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal  } else if (error->IsOngoing()) {
114046c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal    // |error| IsOngoing at entry to this method, but no device
114146c27cc8f83428ce6b290c4d92e73fbcad899457mukesh agrawal    // |deferred|. Reset |error|, to indicate we're done.
1142df7c553368620f718ec14bc6751f232185792870Jason Glasgow    error->Reset();
11439a24553461df7036755060423f90804011612249Eric Shienbrood  }
11449a24553461df7036755060423f90804011612249Eric Shienbrood}
11459a24553461df7036755060423f90804011612249Eric Shienbrood
11469a24553461df7036755060423f90804011612249Eric Shienbroodvoid Manager::UpdateEnabledTechnologies() {
11479a24553461df7036755060423f90804011612249Eric Shienbrood  Error error;
1148923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  adaptor_->EmitStringsChanged(kEnabledTechnologiesProperty,
11499a24553461df7036755060423f90804011612249Eric Shienbrood                               EnabledTechnologies(&error));
11509a24553461df7036755060423f90804011612249Eric Shienbrood}
11519a24553461df7036755060423f90804011612249Eric Shienbrood
11525086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chanvoid Manager::UpdateUninitializedTechnologies() {
11535086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan  Error error;
11545086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan  adaptor_->EmitStringsChanged(kUninitializedTechnologiesProperty,
11555086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan                               UninitializedTechnologies(&error));
11565086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan}
11575086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan
11581d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiuvoid Manager::SetPassiveMode() {
11591d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  CHECK(!device_claimer_);
11601d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  // Create a default device claimer to claim devices from  shill as they're
11611d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  // detected.  Devices will be managed by remote application, which will use
11621d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  // the default claimer to specify the devices for shill to manage.
11631d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  device_claimer_.reset(
11641d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu      new DeviceClaimer(kDefaultClaimerName, &device_info_, true));
11651d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu}
11661d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu
116783d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewartvoid Manager::SetIgnoreUnknownEthernet(bool ignore) {
116883d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewart  LOG(INFO) << __func__ << "(" << ignore << ")";
116983d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewart  ignore_unknown_ethernet_ = ignore;
117083d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewart}
117183d625655edbc7c35fc436b8b8fe744886d0aae1Paul Stewart
11728ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::SetPrependDNSServers(const std::string& prepend_dns_servers) {
1173c5f89d131e5b03f448b73fd02d16cab30e438521Garret Kelly  props_.prepend_dns_servers = prepend_dns_servers;
1174c5f89d131e5b03f448b73fd02d16cab30e438521Garret Kelly}
1175c5f89d131e5b03f448b73fd02d16cab30e438521Garret Kelly
11768ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::SetAcceptHostnameFrom(const string& hostname_from) {
117708add488849f90600a5657a6f54f4dbc34701b8fMatthew Wein  accept_hostname_from_ = hostname_from;
117808add488849f90600a5657a6f54f4dbc34701b8fMatthew Wein}
117908add488849f90600a5657a6f54f4dbc34701b8fMatthew Wein
11808ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::ShouldAcceptHostnameFrom(const string& device_name) const {
11813a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko  return base::MatchPattern(device_name, accept_hostname_from_);
118208add488849f90600a5657a6f54f4dbc34701b8fMatthew Wein}
118308add488849f90600a5657a6f54f4dbc34701b8fMatthew Wein
11848ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::SetDHCPv6EnabledDevices(const vector<string>& device_list) {
1185d48fa0c5531e2102d4f537e81b9f92afc2d60955Peter Qiu  dhcpv6_enabled_devices_ = device_list;
1186d48fa0c5531e2102d4f537e81b9f92afc2d60955Peter Qiu}
1187d48fa0c5531e2102d4f537e81b9f92afc2d60955Peter Qiu
11888ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::IsDHCPv6EnabledForDevice(const string& device_name) const {
1189d48fa0c5531e2102d4f537e81b9f92afc2d60955Peter Qiu  return std::find(dhcpv6_enabled_devices_.begin(),
1190d48fa0c5531e2102d4f537e81b9f92afc2d60955Peter Qiu                   dhcpv6_enabled_devices_.end(),
1191d48fa0c5531e2102d4f537e81b9f92afc2d60955Peter Qiu                   device_name) != dhcpv6_enabled_devices_.end();
1192d48fa0c5531e2102d4f537e81b9f92afc2d60955Peter Qiu}
1193d48fa0c5531e2102d4f537e81b9f92afc2d60955Peter Qiu
11941ce231c71932200e4d02c71567f8e93788120781Paul Stewartvector<string> Manager::FilterPrependDNSServersByFamily(
11951ce231c71932200e4d02c71567f8e93788120781Paul Stewart    IPAddress::Family family) const {
11961ce231c71932200e4d02c71567f8e93788120781Paul Stewart  vector<string> dns_servers;
11973a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko  vector<string> split_servers = base::SplitString(
11983a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko      props_.prepend_dns_servers, ",", base::TRIM_WHITESPACE,
11993a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko      base::SPLIT_WANT_ALL);
12008ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& server : split_servers) {
1201c5f89d131e5b03f448b73fd02d16cab30e438521Garret Kelly    const IPAddress address(server);
1202c5f89d131e5b03f448b73fd02d16cab30e438521Garret Kelly    if (address.family() == family) {
12031ce231c71932200e4d02c71567f8e93788120781Paul Stewart      dns_servers.push_back(server);
1204c5f89d131e5b03f448b73fd02d16cab30e438521Garret Kelly    }
1205c5f89d131e5b03f448b73fd02d16cab30e438521Garret Kelly  }
12061ce231c71932200e4d02c71567f8e93788120781Paul Stewart  return dns_servers;
1207c5f89d131e5b03f448b73fd02d16cab30e438521Garret Kelly}
1208c5f89d131e5b03f448b73fd02d16cab30e438521Garret Kelly
12092d36a6e266deb96db1d3cf4b18dcc9d863795f28Samuel Tanbool Manager::IsSuspending() {
12102d36a6e266deb96db1d3cf4b18dcc9d863795f28Samuel Tan  if (power_manager_ && power_manager_->suspending()) {
12112d36a6e266deb96db1d3cf4b18dcc9d863795f28Samuel Tan    return true;
12122d36a6e266deb96db1d3cf4b18dcc9d863795f28Samuel Tan  }
12132d36a6e266deb96db1d3cf4b18dcc9d863795f28Samuel Tan  return false;
12142d36a6e266deb96db1d3cf4b18dcc9d863795f28Samuel Tan}
12152d36a6e266deb96db1d3cf4b18dcc9d863795f28Samuel Tan
12168ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::RecordDarkResumeWakeReason(const string& wake_reason) {
12171897afaeb89003f5cc75a256f6fd7528e6abd54fSamuel Tan  power_manager_->RecordDarkResumeWakeReason(wake_reason);
12181897afaeb89003f5cc75a256f6fd7528e6abd54fSamuel Tan}
12191897afaeb89003f5cc75a256f6fd7528e6abd54fSamuel Tan
12208ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::RegisterDevice(const DeviceRefPtr& to_manage) {
1221e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov  LOG(INFO) << "Device " << to_manage->FriendlyName() << " registered.";
12221d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  // Manager is running in passive mode when default claimer is created, which
12231d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  // means devices are being managed by remote application. Only manage the
12241d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  // device if it was explicitly released by remote application through
12251d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  // default claimer.
12261d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  if (device_claimer_ && device_claimer_->default_claimer()) {
12271d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu    if (!device_claimer_->IsDeviceReleased(to_manage->link_name())) {
12281d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu      Error error;
12291d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu      device_claimer_->Claim(to_manage->link_name(), &error);
12301d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu      return;
12311d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu    }
12321d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu  }
12331d499ed2d5eede24f55c7f6b8aaba06136ef4f22Peter Qiu
12348ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
12356db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (to_manage == device)
12369be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone      return;
12379be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone  }
1238c1e50412f45518e23d51ba8bb8694c366943d945Chris Masone  devices_.push_back(to_manage);
1239f1ce5d27adbfcaf9c46e650252b46e02b0d8addaPaul Stewart
124087a4ae88915e3dc22dbb1327002e1daf769ef23ePaul Stewart  LoadDeviceFromProfiles(to_manage);
1241a41e38d57e4fa37bd2c8de6447890b4e1951acb7Paul Stewart
1242ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  if (IsTechnologyProhibited(to_manage->technology())) {
1243ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart    Error unused_error;
1244b0d2f64a672a970a7dc1f846c36c0cd411177662Rebecca Silberstein    to_manage->SetEnabledNonPersistent(false, &unused_error, ResultCallback());
1245ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  }
1246ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart
1247e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov  // If |to_manage| is new, it needs to be persisted.
1248e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov  UpdateDevice(to_manage);
1249e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov
1250a41e38d57e4fa37bd2c8de6447890b4e1951acb7Paul Stewart  // In normal usage, running_ will always be true when we are here, however
1251a41e38d57e4fa37bd2c8de6447890b4e1951acb7Paul Stewart  // unit tests sometimes do things in otherwise invalid states.
12527fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood  if (running_ && (to_manage->enabled_persistent() ||
12537fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood                   to_manage->IsUnderlyingDeviceEnabled()))
12549a24553461df7036755060423f90804011612249Eric Shienbrood    to_manage->SetEnabled(true);
1255435de2cd55a95836381b53acbce8cbbad98ec04dGaurav Shah
12568839a899af928671d87b12073bebc5f1b2752a30Eric Shienbrood  EmitDeviceProperties();
12579be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone}
12589be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone
12598ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::DeregisterDevice(const DeviceRefPtr& to_forget) {
1260c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << __func__ << "(" << to_forget->FriendlyName() << ")";
12616db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart  for (auto it = devices_.begin(); it != devices_.end(); ++it) {
1262c1e50412f45518e23d51ba8bb8694c366943d945Chris Masone    if (to_forget.get() == it->get()) {
1263c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein      SLOG(this, 2) << "Deregistered device: " << to_forget->UniqueName();
1264212d60f4de8a17702dc824f4a56d7de884e18e27Paul Stewart      UpdateDevice(to_forget);
12659a24553461df7036755060423f90804011612249Eric Shienbrood      to_forget->SetEnabled(false);
12669be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone      devices_.erase(it);
12678839a899af928671d87b12073bebc5f1b2752a30Eric Shienbrood      EmitDeviceProperties();
12689be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone      return;
12699be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone    }
12709be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone  }
1271c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << __func__ << " unknown device: "
1272c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                << to_forget->UniqueName();
12739be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone}
12749be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone
12758ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::DeregisterDeviceByLinkName(const string& link_name) {
12767e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  for (const auto& device : devices_) {
12777e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu    if (device->link_name() == link_name) {
12787e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu      DeregisterDevice(device);
12797e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu      break;
12807e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu    }
12817e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu  }
12827e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu}
12837e8b8ee34816575b9059dd041ef29f91fe1d15c8Peter Qiu
12848ae18741780300de3126826b72593391f2d00313Paul Stewartvector<string> Manager::ClaimedDevices(Error* error) {
1285babfe5a5e1f7b11a70fdf616b8479166416810c9Garret Kelly  vector<string> results;
1286babfe5a5e1f7b11a70fdf616b8479166416810c9Garret Kelly  if (!device_claimer_) {
1287babfe5a5e1f7b11a70fdf616b8479166416810c9Garret Kelly    return results;
1288babfe5a5e1f7b11a70fdf616b8479166416810c9Garret Kelly  }
1289babfe5a5e1f7b11a70fdf616b8479166416810c9Garret Kelly
12908ae18741780300de3126826b72593391f2d00313Paul Stewart  const auto& devices = device_claimer_->claimed_device_names();
1291babfe5a5e1f7b11a70fdf616b8479166416810c9Garret Kelly  results.resize(devices.size());
1292babfe5a5e1f7b11a70fdf616b8479166416810c9Garret Kelly  std::copy(devices.begin(), devices.end(), results.begin());
1293babfe5a5e1f7b11a70fdf616b8479166416810c9Garret Kelly  return results;
1294babfe5a5e1f7b11a70fdf616b8479166416810c9Garret Kelly}
1295babfe5a5e1f7b11a70fdf616b8479166416810c9Garret Kelly
12968ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::LoadDeviceFromProfiles(const DeviceRefPtr& device) {
129787a4ae88915e3dc22dbb1327002e1daf769ef23ePaul Stewart  // We are applying device properties from the DefaultProfile, and adding the
129887a4ae88915e3dc22dbb1327002e1daf769ef23ePaul Stewart  // union of hidden services in all loaded profiles to the device.
12998ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& profile : profiles_) {
130087a4ae88915e3dc22dbb1327002e1daf769ef23ePaul Stewart    // Load device configuration, if any exists, as well as hidden services.
13016db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    profile->ConfigureDevice(device);
130287a4ae88915e3dc22dbb1327002e1daf769ef23ePaul Stewart  }
130387a4ae88915e3dc22dbb1327002e1daf769ef23ePaul Stewart}
130487a4ae88915e3dc22dbb1327002e1daf769ef23ePaul Stewart
13058839a899af928671d87b12073bebc5f1b2752a30Eric Shienbroodvoid Manager::EmitDeviceProperties() {
13069b6f8b8cdeb0c9e925fad635cc52a467c82741d0Peter Qiu  Error error;
13079b6f8b8cdeb0c9e925fad635cc52a467c82741d0Peter Qiu  vector<string> device_paths = EnumerateDevices(&error);
1308923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  adaptor_->EmitRpcIdentifierArrayChanged(kDevicesProperty,
13098839a899af928671d87b12073bebc5f1b2752a30Eric Shienbrood                                          device_paths);
1310923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  adaptor_->EmitStringsChanged(kAvailableTechnologiesProperty,
13118839a899af928671d87b12073bebc5f1b2752a30Eric Shienbrood                               AvailableTechnologies(&error));
1312923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  adaptor_->EmitStringsChanged(kEnabledTechnologiesProperty,
13138839a899af928671d87b12073bebc5f1b2752a30Eric Shienbrood                               EnabledTechnologies(&error));
13145086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan  adaptor_->EmitStringsChanged(kUninitializedTechnologiesProperty,
13155086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan                               UninitializedTechnologies(&error));
13168839a899af928671d87b12073bebc5f1b2752a30Eric Shienbrood}
13178839a899af928671d87b12073bebc5f1b2752a30Eric Shienbrood
13189b6f8b8cdeb0c9e925fad635cc52a467c82741d0Peter Qiuvoid Manager::OnInnerDevicesChanged() {
13199b6f8b8cdeb0c9e925fad635cc52a467c82741d0Peter Qiu  EmitDeviceProperties();
13209b6f8b8cdeb0c9e925fad635cc52a467c82741d0Peter Qiu}
13219b6f8b8cdeb0c9e925fad635cc52a467c82741d0Peter Qiu
13228a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tanvoid Manager::OnDeviceClaimerVanished() {
13238a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan  // Reset device claimer.
13248a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan  device_claimer_.reset();
13258a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan}
13268a3f68edbcf7fe59380609588787baa54cbd9bddSamuel Tan
13271a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIFI)
13288ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::SetDisableWiFiVHT(const bool& disable_wifi_vht, Error* error) {
13299d97b7deda3ae604d718873207a951f62d418b34Paul Stewart  if (disable_wifi_vht == wifi_provider_->disable_vht()) {
13309d97b7deda3ae604d718873207a951f62d418b34Paul Stewart    return false;
13319d97b7deda3ae604d718873207a951f62d418b34Paul Stewart  }
13329d97b7deda3ae604d718873207a951f62d418b34Paul Stewart  wifi_provider_->set_disable_vht(disable_wifi_vht);
13339d97b7deda3ae604d718873207a951f62d418b34Paul Stewart  return true;
13349d97b7deda3ae604d718873207a951f62d418b34Paul Stewart}
13359d97b7deda3ae604d718873207a951f62d418b34Paul Stewart
13368ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::GetDisableWiFiVHT(Error* error) {
13379d97b7deda3ae604d718873207a951f62d418b34Paul Stewart  return wifi_provider_->disable_vht();
13389d97b7deda3ae604d718873207a951f62d418b34Paul Stewart}
13391a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif  // DISABLE_WIFI
13409d97b7deda3ae604d718873207a951f62d418b34Paul Stewart
13418ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::SetProhibitedTechnologies(const string& prohibited_technologies,
13428ae18741780300de3126826b72593391f2d00313Paul Stewart                                        Error* error) {
1343ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  vector<Technology::Identifier> technology_vector;
1344ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  if (!Technology::GetTechnologyVectorFromString(prohibited_technologies,
1345ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart                                                 &technology_vector,
1346ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart                                                 error)) {
1347ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart    return false;
1348ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  }
13498ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& technology : technology_vector) {
1350ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart    Error unused_error(Error::kOperationInitiated);
1351ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart    ResultCallback result_callback(Bind(
1352ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart        &Manager::OnTechnologyProhibited, Unretained(this), technology));
1353b0d2f64a672a970a7dc1f846c36c0cd411177662Rebecca Silberstein    const bool kPersistentSave = false;
1354ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart    SetEnabledStateForTechnology(Technology::NameFromIdentifier(technology),
1355ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart                                 false,
1356b0d2f64a672a970a7dc1f846c36c0cd411177662Rebecca Silberstein                                 kPersistentSave,
1357ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart                                 &unused_error,
1358ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart                                 result_callback);
1359ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  }
1360ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  props_.prohibited_technologies = prohibited_technologies;
1361ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart
1362ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  return true;
1363ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart}
1364ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart
1365ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewartvoid Manager::OnTechnologyProhibited(Technology::Identifier technology,
13668ae18741780300de3126826b72593391f2d00313Paul Stewart                                     const Error& error) {
1367ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  SLOG(this, 2) << __func__ << " for "
1368ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart                << Technology::NameFromIdentifier(technology);
1369ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart}
1370ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart
13718ae18741780300de3126826b72593391f2d00313Paul Stewartstring Manager::GetProhibitedTechnologies(Error* error) {
1372ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart  return props_.prohibited_technologies;
1373ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart}
1374ff6be29bd74abd31640abcf9ad4332e0a9657196Paul Stewart
13758ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::HasService(const ServiceRefPtr& service) {
13768ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& manager_service : services_) {
13776db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (manager_service->unique_name() == service->unique_name())
13784eb4d782b83850552af41f675d22250601b9fb8dmukesh agrawal      return true;
13794eb4d782b83850552af41f675d22250601b9fb8dmukesh agrawal  }
13804eb4d782b83850552af41f675d22250601b9fb8dmukesh agrawal  return false;
13814eb4d782b83850552af41f675d22250601b9fb8dmukesh agrawal}
13824eb4d782b83850552af41f675d22250601b9fb8dmukesh agrawal
13838ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::RegisterService(const ServiceRefPtr& to_manage) {
1384c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << "Registering service " << to_manage->unique_name();
1385d835b2079b1b0f67338d48f528d61f882fa77693mukesh agrawal
13867522551440b9a287bccf2d95a42357d04ab79814Paul Stewart  MatchProfileWithService(to_manage);
13876791a43add38926966bd420e89541717fb2cb2b5Chris Masone
13886791a43add38926966bd420e89541717fb2cb2b5Chris Masone  // Now add to OUR list.
13898ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_) {
13906db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    CHECK(to_manage->unique_name() != service->unique_name());
13919be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone  }
1392c1e50412f45518e23d51ba8bb8694c366943d945Chris Masone  services_.push_back(to_manage);
139322aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart  SortServices();
13949be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone}
13959be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone
13968ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::DeregisterService(const ServiceRefPtr& to_forget) {
13976813e7624f1047872eeceec14db45373e30e268emukesh agrawal  for (auto it = services_.begin(); it != services_.end(); ++it) {
1398457728b3eeb2d67c980e0d20675f0a0f750903e1Darin Petkov    if (to_forget->unique_name() == (*it)->unique_name()) {
13996813e7624f1047872eeceec14db45373e30e268emukesh agrawal      DLOG_IF(FATAL, (*it)->connection())
14006813e7624f1047872eeceec14db45373e30e268emukesh agrawal          << "Service " << (*it)->unique_name()
14016813e7624f1047872eeceec14db45373e30e268emukesh agrawal          << " still has a connection (in call to " << __func__ << ")";
1402fc9a1da93210ff11eb9895430e9cc60d3e4b4a53Paul Stewart      (*it)->Unload();
1403cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan      (*it)->SetProfile(nullptr);
14049be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone      services_.erase(it);
140522aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart      SortServices();
14069be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone      return;
14079be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone    }
14089be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone  }
14099be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone}
14109be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone
14118ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::UnloadService(vector<ServiceRefPtr>::iterator* service_iterator) {
141265512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart  if (!(**service_iterator)->Unload()) {
141365512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart    return false;
141465512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart  }
141565512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart
141665512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart  DCHECK(!(**service_iterator)->connection());
1417cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan  (**service_iterator)->SetProfile(nullptr);
141865512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart  *service_iterator = services_.erase(*service_iterator);
141965512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart
142065512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart  return true;
142165512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart}
142265512e10f0534c390b2ef027cc64f660658db6c0Paul Stewart
14238ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::UpdateService(const ServiceRefPtr& to_update) {
142400917ceafbc28599391bfcdd5837faf6d63fec32mukesh agrawal  CHECK(to_update);
1425220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart  bool is_interesting_state_change = false;
14268ae18741780300de3126826b72593391f2d00313Paul Stewart  const auto& state_it = watched_service_states_.find(to_update->unique_name());
1427220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart  if (state_it != watched_service_states_.end()) {
1428220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart    is_interesting_state_change = (to_update->state() != state_it->second);
1429220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart  } else {
1430220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart    is_interesting_state_change = to_update->IsActive(nullptr);
1431220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart  }
1432220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart
1433220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart  string log_message = StringPrintf(
1434220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart      "Service %s updated; state: %s failure %s",
1435220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart      to_update->unique_name().c_str(),
1436220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart      Service::ConnectStateToString(to_update->state()),
1437220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart      Service::ConnectFailureToString(to_update->failure()));
1438220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart  if (is_interesting_state_change) {
1439220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart    LOG(INFO) << log_message;
1440220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart  } else {
1441220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart    SLOG(this, 2) << log_message;
1442220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart  }
1443c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << "IsConnected(): " << to_update->IsConnected();
1444c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << "IsConnecting(): " << to_update->IsConnecting();
14453d9bcf58bd29080b96db4a2c9e7bfe6ed3d6e6dfPaul Stewart  if (to_update->IsConnected()) {
14462da34c038933eeac36a85550ff54e09611a1d828Paul Stewart    to_update->EnableAndRetainAutoConnect();
14472da34c038933eeac36a85550ff54e09611a1d828Paul Stewart    // Persists the updated auto_connect setting in the profile.
1448d93615e9687b3473ede06a8503b6d23aacd0c603Gary Morain    SaveServiceToProfile(to_update);
14493d9bcf58bd29080b96db4a2c9e7bfe6ed3d6e6dfPaul Stewart  }
145022aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart  SortServices();
145103dba0bccc3a39cded5083212e56713a6d349e01Paul Stewart}
145203dba0bccc3a39cded5083212e56713a6d349e01Paul Stewart
14538ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::UpdateDevice(const DeviceRefPtr& to_update) {
1454e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov  LOG(INFO) << "Device " << to_update->link_name() << " updated: "
1455e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov            << (to_update->enabled_persistent() ? "enabled" : "disabled");
145660a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie  // Saves the device to the topmost profile that accepts it (ordinary
145760a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie  // profiles don't update but default profiles do). Normally, the topmost
145860a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie  // updating profile would be the DefaultProfile at the bottom of the stack.
145960a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie  // Autotests, differ from the normal scenario, however, in that they push a
146060a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie  // second test-only DefaultProfile.
14616db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart  for (auto rit = profiles_.rbegin(); rit != profiles_.rend(); ++rit) {
1462e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov    if ((*rit)->UpdateDevice(to_update)) {
1463e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov      return;
1464e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov    }
1465e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov  }
1466e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov}
1467e7c6ad35cafed32a0fd1390487c74e66eae1961dDarin Petkov
14681a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIFI)
146960a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrievoid Manager::UpdateWiFiProvider() {
147060a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie  // Saves |wifi_provider_| to the topmost profile that accepts it (ordinary
147160a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie  // profiles don't update but default profiles do). Normally, the topmost
147260a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie  // updating profile would be the DefaultProfile at the bottom of the stack.
147360a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie  // Autotests, differ from the normal scenario, however, in that they push a
147460a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie  // second test-only DefaultProfile.
14756db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart  for (auto rit = profiles_.rbegin(); rit != profiles_.rend(); ++rit) {
147660a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie    if ((*rit)->UpdateWiFiProvider(*wifi_provider_)) {
147760a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie      return;
147860a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie    }
147960a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie  }
148060a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie}
14811a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif  // DISABLE_WIFI
148260a3706bee5686ae2322a774b9e7d5e8e63fcaf7Wade Guthrie
14838ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::SaveServiceToProfile(const ServiceRefPtr& to_update) {
1484d93615e9687b3473ede06a8503b6d23aacd0c603Gary Morain  if (IsServiceEphemeral(to_update)) {
1485d93615e9687b3473ede06a8503b6d23aacd0c603Gary Morain    if (profiles_.empty()) {
1486d93615e9687b3473ede06a8503b6d23aacd0c603Gary Morain      LOG(ERROR) << "Cannot assign profile to service: no profiles exist!";
1487d93615e9687b3473ede06a8503b6d23aacd0c603Gary Morain    } else {
1488d93615e9687b3473ede06a8503b6d23aacd0c603Gary Morain      MoveServiceToProfile(to_update, profiles_.back());
1489d93615e9687b3473ede06a8503b6d23aacd0c603Gary Morain    }
1490d93615e9687b3473ede06a8503b6d23aacd0c603Gary Morain  } else {
1491d93615e9687b3473ede06a8503b6d23aacd0c603Gary Morain    to_update->profile()->UpdateService(to_update);
1492d93615e9687b3473ede06a8503b6d23aacd0c603Gary Morain  }
1493d93615e9687b3473ede06a8503b6d23aacd0c603Gary Morain}
1494d93615e9687b3473ede06a8503b6d23aacd0c603Gary Morain
14958ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::LoadProperties(const scoped_refptr<DefaultProfile>& profile) {
149615d5431798155cc83a3fcb8abe0d1a2d5128f7b6Rebecca Silberstein  profile->LoadManagerProperties(&props_, dhcp_properties_.get());
1497cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan  SetIgnoredDNSSearchPaths(props_.ignored_dns_search_paths, nullptr);
14984d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart}
14994d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart
15008ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::AddTerminationAction(const string& name,
15018ae18741780300de3126826b72593391f2d00313Paul Stewart                                   const base::Closure& start) {
1502a9fb325a645e0be17b3eaa26a4d0f1d5228683c9Gary Morain  termination_actions_.Add(name, start);
1503a9fb325a645e0be17b3eaa26a4d0f1d5228683c9Gary Morain}
1504a9fb325a645e0be17b3eaa26a4d0f1d5228683c9Gary Morain
15058ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::TerminationActionComplete(const string& name) {
1506c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << __func__;
1507a9fb325a645e0be17b3eaa26a4d0f1d5228683c9Gary Morain  termination_actions_.ActionComplete(name);
1508a9fb325a645e0be17b3eaa26a4d0f1d5228683c9Gary Morain}
1509a9fb325a645e0be17b3eaa26a4d0f1d5228683c9Gary Morain
15108ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::RemoveTerminationAction(const string& name) {
1511c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << __func__;
1512a9fb325a645e0be17b3eaa26a4d0f1d5228683c9Gary Morain  termination_actions_.Remove(name);
1513a9fb325a645e0be17b3eaa26a4d0f1d5228683c9Gary Morain}
1514a9fb325a645e0be17b3eaa26a4d0f1d5228683c9Gary Morain
15158ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::RunTerminationActions(const ResultCallback& done_callback) {
15163ec553401f04d005cfce24411cd63929557dea75Darin Petkov  LOG(INFO) << "Running termination actions.";
15173fbf8bd4508f35cc3aec35e8ec562dd37eeb282cBen Chan  termination_actions_.Run(kTerminationActionsTimeoutMilliseconds,
15183fbf8bd4508f35cc3aec35e8ec562dd37eeb282cBen Chan                           done_callback);
1519a9fb325a645e0be17b3eaa26a4d0f1d5228683c9Gary Morain}
1520a9fb325a645e0be17b3eaa26a4d0f1d5228683c9Gary Morain
1521ab22c166ccfb33fd99169bee645d67306ae26cedArman Uguraybool Manager::RunTerminationActionsAndNotifyMetrics(
15228ae18741780300de3126826b72593391f2d00313Paul Stewart    const ResultCallback& done_callback) {
1523ab22c166ccfb33fd99169bee645d67306ae26cedArman Uguray  if (termination_actions_.IsEmpty())
1524ab22c166ccfb33fd99169bee645d67306ae26cedArman Uguray    return false;
1525ab22c166ccfb33fd99169bee645d67306ae26cedArman Uguray
1526fbe8d2b361a51e89fcf1207050729be86a961f5fSamuel Tan  metrics_->NotifyTerminationActionsStarted();
15273fbf8bd4508f35cc3aec35e8ec562dd37eeb282cBen Chan  RunTerminationActions(done_callback);
1528ab22c166ccfb33fd99169bee645d67306ae26cedArman Uguray  return true;
1529ab22c166ccfb33fd99169bee645d67306ae26cedArman Uguray}
1530ab22c166ccfb33fd99169bee645d67306ae26cedArman Uguray
15318ae18741780300de3126826b72593391f2d00313Paul Stewartint Manager::RegisterDefaultServiceCallback(const ServiceCallback& callback) {
1532a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  default_service_callbacks_[++default_service_callback_tag_] = callback;
1533a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  return default_service_callback_tag_;
1534a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov}
1535a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov
1536a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkovvoid Manager::DeregisterDefaultServiceCallback(int tag) {
1537a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  default_service_callbacks_.erase(tag);
1538a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov}
1539a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov
15401a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIFI)
15418ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::VerifyDestination(const string& certificate,
15428ae18741780300de3126826b72593391f2d00313Paul Stewart                                const string& public_key,
15438ae18741780300de3126826b72593391f2d00313Paul Stewart                                const string& nonce,
15448ae18741780300de3126826b72593391f2d00313Paul Stewart                                const string& signed_data,
15458ae18741780300de3126826b72593391f2d00313Paul Stewart                                const string& destination_udn,
15468ae18741780300de3126826b72593391f2d00313Paul Stewart                                const string& hotspot_ssid,
15478ae18741780300de3126826b72593391f2d00313Paul Stewart                                const string& hotspot_bssid,
15488ae18741780300de3126826b72593391f2d00313Paul Stewart                                const ResultBoolCallback& cb,
15498ae18741780300de3126826b72593391f2d00313Paul Stewart                                Error* error) {
1550cdde79fe1eeae3274ab343e32d87c7ba4c0ef4deChristopher Wiley  if (hotspot_bssid.length() > 32) {
1551cdde79fe1eeae3274ab343e32d87c7ba4c0ef4deChristopher Wiley    error->Populate(Error::kOperationFailed,
1552cdde79fe1eeae3274ab343e32d87c7ba4c0ef4deChristopher Wiley                    "Invalid SSID given for verification.");
1553cdde79fe1eeae3274ab343e32d87c7ba4c0ef4deChristopher Wiley    return;
1554cdde79fe1eeae3274ab343e32d87c7ba4c0ef4deChristopher Wiley  }
15558388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley  vector<uint8_t> ssid;
15568388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley  string bssid;
1557cdde79fe1eeae3274ab343e32d87c7ba4c0ef4deChristopher Wiley  if (hotspot_ssid.length() || hotspot_bssid.length()) {
15588388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley    // If Chrome thinks this destination is already configured, service
15598388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley    // will be an AP that both we and the destination are connected
15608388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley    // to, and not the thing we should verify against.
1561cdde79fe1eeae3274ab343e32d87c7ba4c0ef4deChristopher Wiley    ssid.assign(hotspot_ssid.begin(), hotspot_ssid.end());
1562cdde79fe1eeae3274ab343e32d87c7ba4c0ef4deChristopher Wiley    bssid = hotspot_bssid;
15638388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley  } else {
15648388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley    // For now, we only support a single connected WiFi service.  If we change
15658388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley    // that, we'll need to revisit this.
15668388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley    bool found_one = false;
15678ae18741780300de3126826b72593391f2d00313Paul Stewart    for (const auto& service : services_) {
15688388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley      if (service->technology() == Technology::kWifi &&
15698388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley          service->IsConnected()) {
15708ae18741780300de3126826b72593391f2d00313Paul Stewart        WiFiService* wifi = reinterpret_cast<WiFiService*>(&(*service));
15718388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley        bssid = wifi->bssid();
15728388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley        ssid = wifi->ssid();
15738388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley        found_one = true;
15748388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley        break;
15758388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley      }
15768388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley    }
15778388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley    if (!found_one) {
15788388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley      error->Populate(Error::kOperationFailed,
15798388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley                      "Unable to find connected WiFi service.");
15808388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley      return;
15818388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley    }
1582cdde79fe1eeae3274ab343e32d87c7ba4c0ef4deChristopher Wiley  }
15831057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley  crypto_util_proxy_->VerifyDestination(certificate, public_key, nonce,
15841057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley                                        signed_data, destination_udn,
15858388986acde2e1cdc2e211f7247bbe40f9e1f1a5Christopher Wiley                                        ssid, bssid, cb, error);
15861057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley}
15871057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley
15881057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wileyvoid Manager::VerifyToEncryptLink(string public_key,
15891057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley                                  string data,
15901057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley                                  ResultStringCallback cb,
15918ae18741780300de3126826b72593391f2d00313Paul Stewart                                  const Error& error,
15921057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley                                  bool success) {
15931057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley  if (!success || !error.IsSuccess()) {
15941057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley    CHECK(error.IsFailure()) << "Return code from CryptoUtilProxy "
15951057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley                             << "inconsistent with error code.";
15961057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley    cb.Run(error, "");
15971057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley    return;
15981057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley  }
15991057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley  Error encrypt_error;
16001057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley  if (!crypto_util_proxy_->EncryptData(public_key, data, cb, &encrypt_error)) {
1601b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley    CHECK(encrypt_error.IsFailure()) << "CryptoUtilProxy::EncryptData returned "
1602b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley                                     << "inconsistently.";
1603b3e70d2ca1cfb02effd82c6f95f2869d22201860Christopher Wiley    cb.Run(encrypt_error, "");
16041057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley  }
16050d9cf0cb47c86a1f7fff0e2b8e351bcd0478e9b6Christopher Wiley}
16060d9cf0cb47c86a1f7fff0e2b8e351bcd0478e9b6Christopher Wiley
16078ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::VerifyAndEncryptData(const string& certificate,
16088ae18741780300de3126826b72593391f2d00313Paul Stewart                                   const string& public_key,
16098ae18741780300de3126826b72593391f2d00313Paul Stewart                                   const string& nonce,
16108ae18741780300de3126826b72593391f2d00313Paul Stewart                                   const string& signed_data,
16118ae18741780300de3126826b72593391f2d00313Paul Stewart                                   const string& destination_udn,
16128ae18741780300de3126826b72593391f2d00313Paul Stewart                                   const string& hotspot_ssid,
16138ae18741780300de3126826b72593391f2d00313Paul Stewart                                   const string& hotspot_bssid,
16148ae18741780300de3126826b72593391f2d00313Paul Stewart                                   const string& data,
16158ae18741780300de3126826b72593391f2d00313Paul Stewart                                   const ResultStringCallback& cb,
16168ae18741780300de3126826b72593391f2d00313Paul Stewart                                   Error* error) {
16171057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley  ResultBoolCallback on_verification_success = Bind(
16181057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley      &Manager::VerifyToEncryptLink, AsWeakPtr(), public_key, data, cb);
16191057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley  VerifyDestination(certificate, public_key, nonce, signed_data,
1620cdde79fe1eeae3274ab343e32d87c7ba4c0ef4deChristopher Wiley                    destination_udn, hotspot_ssid, hotspot_bssid,
1621cdde79fe1eeae3274ab343e32d87c7ba4c0ef4deChristopher Wiley                    on_verification_success, error);
16220d9cf0cb47c86a1f7fff0e2b8e351bcd0478e9b6Christopher Wiley}
16230d9cf0cb47c86a1f7fff0e2b8e351bcd0478e9b6Christopher Wiley
16248ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::VerifyAndEncryptCredentials(const string& certificate,
16258ae18741780300de3126826b72593391f2d00313Paul Stewart                                          const string& public_key,
16268ae18741780300de3126826b72593391f2d00313Paul Stewart                                          const string& nonce,
16278ae18741780300de3126826b72593391f2d00313Paul Stewart                                          const string& signed_data,
16288ae18741780300de3126826b72593391f2d00313Paul Stewart                                          const string& destination_udn,
16298ae18741780300de3126826b72593391f2d00313Paul Stewart                                          const string& hotspot_ssid,
16308ae18741780300de3126826b72593391f2d00313Paul Stewart                                          const string& hotspot_bssid,
16318ae18741780300de3126826b72593391f2d00313Paul Stewart                                          const string& network_path,
16328ae18741780300de3126826b72593391f2d00313Paul Stewart                                          const ResultStringCallback& cb,
16338ae18741780300de3126826b72593391f2d00313Paul Stewart                                          Error* error) {
16341057cd706c91b1a5fc3a99c5a9bfa4f24a98e283Christopher Wiley  // This is intentionally left unimplemented until we have a security review.
16350d9cf0cb47c86a1f7fff0e2b8e351bcd0478e9b6Christopher Wiley  error->Populate(Error::kNotImplemented, "Not implemented");
16360d9cf0cb47c86a1f7fff0e2b8e351bcd0478e9b6Christopher Wiley}
16371a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif  // DISABLE_WIFI
16380d9cf0cb47c86a1f7fff0e2b8e351bcd0478e9b6Christopher Wiley
16399d58193108f55edf0f06cd54f44464da633cb8aaPeter Qiuint Manager::CalcConnectionId(std::string gateway_ip,
16409d58193108f55edf0f06cd54f44464da633cb8aaPeter Qiu                              std::string gateway_mac) {
16418a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko  return static_cast<int>(std::hash<std::string>()(gateway_ip + gateway_mac +
16429d58193108f55edf0f06cd54f44464da633cb8aaPeter Qiu      std::to_string(props_.connection_id_salt)));
16439d58193108f55edf0f06cd54f44464da633cb8aaPeter Qiu}
16449d58193108f55edf0f06cd54f44464da633cb8aaPeter Qiu
16459d58193108f55edf0f06cd54f44464da633cb8aaPeter Qiuvoid Manager::ReportServicesOnSameNetwork(int connection_id) {
16469d58193108f55edf0f06cd54f44464da633cb8aaPeter Qiu  int num_services = 0;
16478ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_) {
16489d58193108f55edf0f06cd54f44464da633cb8aaPeter Qiu    if (service->connection_id() == connection_id) {
16499d58193108f55edf0f06cd54f44464da633cb8aaPeter Qiu      num_services++;
16509d58193108f55edf0f06cd54f44464da633cb8aaPeter Qiu    }
16519d58193108f55edf0f06cd54f44464da633cb8aaPeter Qiu  }
16529d58193108f55edf0f06cd54f44464da633cb8aaPeter Qiu  metrics_->NotifyServicesOnSameNetwork(num_services);
16539d58193108f55edf0f06cd54f44464da633cb8aaPeter Qiu}
16549d58193108f55edf0f06cd54f44464da633cb8aaPeter Qiu
16558ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::NotifyDefaultServiceChanged(const ServiceRefPtr& service) {
16568ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& callback : default_service_callbacks_) {
16576db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    callback.second.Run(service);
1658a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  }
16590951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko  metrics_->NotifyDefaultServiceChanged(service.get());
166049739c08a76187fae6494c61e960eec315960715Paul Stewart  EmitDefaultService();
166149739c08a76187fae6494c61e960eec315960715Paul Stewart}
166249739c08a76187fae6494c61e960eec315960715Paul Stewart
166349739c08a76187fae6494c61e960eec315960715Paul Stewartvoid Manager::EmitDefaultService() {
1664cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan  RpcIdentifier rpc_identifier = GetDefaultServiceRpcIdentifier(nullptr);
166549739c08a76187fae6494c61e960eec315960715Paul Stewart  if (rpc_identifier != default_service_rpc_identifier_) {
166639a7beb18a0c24c9b73c3cc49008ccdca19f9ac2Ben Chan    adaptor_->EmitRpcIdentifierChanged(kDefaultServiceProperty, rpc_identifier);
166749739c08a76187fae6494c61e960eec315960715Paul Stewart    default_service_rpc_identifier_ = rpc_identifier;
166849739c08a76187fae6494c61e960eec315960715Paul Stewart  }
1669a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov}
1670a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov
16719fdb84ba0ac2eb56961c90bba592481af493a10fPrathmesh Prabhuvoid Manager::OnSuspendImminent() {
167268b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan  metrics_->NotifySuspendActionsStarted();
1673fbe8d2b361a51e89fcf1207050729be86a961f5fSamuel Tan  if (devices_.empty()) {
1674fbe8d2b361a51e89fcf1207050729be86a961f5fSamuel Tan    // If there are no devices, then suspend actions succeeded synchronously.
1675fbe8d2b361a51e89fcf1207050729be86a961f5fSamuel Tan    // Make a call to the Manager::OnSuspendActionsComplete directly, since
1676fbe8d2b361a51e89fcf1207050729be86a961f5fSamuel Tan    // result_aggregator will not.
1677fbe8d2b361a51e89fcf1207050729be86a961f5fSamuel Tan    OnSuspendActionsComplete(Error(Error::kSuccess));
1678fbe8d2b361a51e89fcf1207050729be86a961f5fSamuel Tan    return;
1679fac0953b10f3c13f47ecd588c0f9a0382bc32776Daniel Erat  }
168068b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan  auto result_aggregator(make_scoped_refptr(new ResultAggregator(
168168b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan      Bind(&Manager::OnSuspendActionsComplete, AsWeakPtr()), dispatcher_,
168268b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan      kTerminationActionsTimeoutMilliseconds)));
16838ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
1684fbe8d2b361a51e89fcf1207050729be86a961f5fSamuel Tan    ResultCallback aggregator_callback(
1685fbe8d2b361a51e89fcf1207050729be86a961f5fSamuel Tan        Bind(&ResultAggregator::ReportResult, result_aggregator));
1686fbe8d2b361a51e89fcf1207050729be86a961f5fSamuel Tan    device->OnBeforeSuspend(aggregator_callback);
1687ca62154261be3d481c1e54d5fcf7012e8918b4e2Darin Petkov  }
1688ca62154261be3d481c1e54d5fcf7012e8918b4e2Darin Petkov}
1689ca62154261be3d481c1e54d5fcf7012e8918b4e2Darin Petkov
16909fdb84ba0ac2eb56961c90bba592481af493a10fPrathmesh Prabhuvoid Manager::OnSuspendDone() {
1691fac0953b10f3c13f47ecd588c0f9a0382bc32776Daniel Erat  metrics_->NotifySuspendDone();
1692381a0bb9927ded7963004fcd6793a77a3fca327bSamuel Tan  // Un-suppress auto-connect in case this flag was left set in dark resume.
1693381a0bb9927ded7963004fcd6793a77a3fca327bSamuel Tan  set_suppress_autoconnect(false);
16948ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_) {
16956db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    service->OnAfterResume();
1696fac0953b10f3c13f47ecd588c0f9a0382bc32776Daniel Erat  }
1697fac0953b10f3c13f47ecd588c0f9a0382bc32776Daniel Erat  SortServices();
16988ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
16996db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    device->OnAfterResume();
1700ab22c166ccfb33fd99169bee645d67306ae26cedArman Uguray  }
17013ec553401f04d005cfce24411cd63929557dea75Darin Petkov}
17023ec553401f04d005cfce24411cd63929557dea75Darin Petkov
170364ad2383c4555a99f4f09fe8f5faa088f99f5b90Prathmesh Prabhuvoid Manager::OnDarkSuspendImminent() {
170468b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan  metrics_->NotifyDarkResumeActionsStarted();
170568b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan  if (devices_.empty()) {
170668b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan    // If there are no devices, then suspend actions succeeded synchronously.
170768b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan    // Make a call to the Manager::OnDarkResumeActionsComplete directly, since
170868b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan    // result_aggregator will not.
170968b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan    OnDarkResumeActionsComplete(Error(Error::kSuccess));
171068b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan    return;
171164ad2383c4555a99f4f09fe8f5faa088f99f5b90Prathmesh Prabhu  }
171268b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan  auto result_aggregator(make_scoped_refptr(new ResultAggregator(
171368b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan      Bind(&Manager::OnDarkResumeActionsComplete, AsWeakPtr()), dispatcher_,
171468b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan      kTerminationActionsTimeoutMilliseconds)));
17158ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
171614ba19b3a0974811187f09f85a912a66963b8f3eSamuel Tan    ResultCallback aggregator_callback(
171714ba19b3a0974811187f09f85a912a66963b8f3eSamuel Tan        Bind(&ResultAggregator::ReportResult, result_aggregator));
171814ba19b3a0974811187f09f85a912a66963b8f3eSamuel Tan    device->OnDarkResume(aggregator_callback);
171964ad2383c4555a99f4f09fe8f5faa088f99f5b90Prathmesh Prabhu  }
172064ad2383c4555a99f4f09fe8f5faa088f99f5b90Prathmesh Prabhu}
172164ad2383c4555a99f4f09fe8f5faa088f99f5b90Prathmesh Prabhu
17228ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::OnSuspendActionsComplete(const Error& error) {
17239fdb84ba0ac2eb56961c90bba592481af493a10fPrathmesh Prabhu  LOG(INFO) << "Finished suspend actions. Result: " << error;
172468b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan  metrics_->NotifySuspendActionsCompleted(error.IsSuccess());
17259fdb84ba0ac2eb56961c90bba592481af493a10fPrathmesh Prabhu  power_manager_->ReportSuspendReadiness();
17263ec553401f04d005cfce24411cd63929557dea75Darin Petkov}
17273ec553401f04d005cfce24411cd63929557dea75Darin Petkov
17288ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::OnDarkResumeActionsComplete(const Error& error) {
172968b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan  LOG(INFO) << "Finished dark resume actions. Result: " << error;
173068b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan  metrics_->NotifyDarkResumeActionsCompleted(error.IsSuccess());
173168b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan  power_manager_->ReportDarkSuspendReadiness();
173268b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan}
173368b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan
173468b73d232e8a03ed55401f36ea1a72a2b69cf912Samuel Tan
1735a9f5dfe4a8db01a2da09ada36d494bec93c6d69fmukesh agrawalvector<DeviceRefPtr>
1736a9f5dfe4a8db01a2da09ada36d494bec93c6d69fmukesh agrawalManager::FilterByTechnology(Technology::Identifier tech) const {
1737a9f5dfe4a8db01a2da09ada36d494bec93c6d69fmukesh agrawal  vector<DeviceRefPtr> found;
17388ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
17396db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (device->technology() == tech)
1740a9f5dfe4a8db01a2da09ada36d494bec93c6d69fmukesh agrawal      found.push_back(device);
17419be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone  }
1742a9f5dfe4a8db01a2da09ada36d494bec93c6d69fmukesh agrawal  return found;
17439be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone}
17449be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone
17458ae18741780300de3126826b72593391f2d00313Paul StewartServiceRefPtr Manager::FindService(const string& name) {
17468ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_) {
17476db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (name == service->unique_name())
17486db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart      return service;
17499be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone  }
1750cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan  return nullptr;
17519be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone}
17529be4a9d1e87d64f850f15061123b2a4334477fa2Chris Masone
175349739c08a76187fae6494c61e960eec315960715Paul Stewartvoid Manager::HelpRegisterConstDerivedRpcIdentifier(
17548ae18741780300de3126826b72593391f2d00313Paul Stewart    const string& name,
17558ae18741780300de3126826b72593391f2d00313Paul Stewart    RpcIdentifier(Manager::*get)(Error* error)) {
175649739c08a76187fae6494c61e960eec315960715Paul Stewart  store_.RegisterDerivedRpcIdentifier(
175749739c08a76187fae6494c61e960eec315960715Paul Stewart      name,
175849739c08a76187fae6494c61e960eec315960715Paul Stewart      RpcIdentifierAccessor(
1759cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan          new CustomAccessor<Manager, RpcIdentifier>(this, get, nullptr)));
176049739c08a76187fae6494c61e960eec315960715Paul Stewart}
176149739c08a76187fae6494c61e960eec315960715Paul Stewart
17622366eede28daa298f240ddbc3c8f36cc0e7b7ad1mukesh agrawalvoid Manager::HelpRegisterConstDerivedRpcIdentifiers(
17638ae18741780300de3126826b72593391f2d00313Paul Stewart    const string& name,
17648ae18741780300de3126826b72593391f2d00313Paul Stewart    RpcIdentifiers(Manager::*get)(Error* error)) {
17652366eede28daa298f240ddbc3c8f36cc0e7b7ad1mukesh agrawal  store_.RegisterDerivedRpcIdentifiers(
17662366eede28daa298f240ddbc3c8f36cc0e7b7ad1mukesh agrawal      name,
17672366eede28daa298f240ddbc3c8f36cc0e7b7ad1mukesh agrawal      RpcIdentifiersAccessor(
1768cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan          new CustomAccessor<Manager, RpcIdentifiers>(this, get, nullptr)));
17692366eede28daa298f240ddbc3c8f36cc0e7b7ad1mukesh agrawal}
17702366eede28daa298f240ddbc3c8f36cc0e7b7ad1mukesh agrawal
1771ffa3d0433d419aa9251f3768a0090a27b6b1c434mukesh agrawalvoid Manager::HelpRegisterDerivedString(
17728ae18741780300de3126826b72593391f2d00313Paul Stewart    const string& name,
17738ae18741780300de3126826b72593391f2d00313Paul Stewart    string(Manager::*get)(Error* error),
17748ae18741780300de3126826b72593391f2d00313Paul Stewart    bool(Manager::*set)(const string&, Error*)) {
177527c4aa55b33d3a3836cf70c8f7094bce1c5ead8cChris Masone  store_.RegisterDerivedString(
177627c4aa55b33d3a3836cf70c8f7094bce1c5ead8cChris Masone      name,
177727c4aa55b33d3a3836cf70c8f7094bce1c5ead8cChris Masone      StringAccessor(new CustomAccessor<Manager, string>(this, get, set)));
1778b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone}
1779b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone
1780bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawalvoid Manager::HelpRegisterConstDerivedStrings(
17818ae18741780300de3126826b72593391f2d00313Paul Stewart    const string& name,
17828ae18741780300de3126826b72593391f2d00313Paul Stewart    Strings(Manager::*get)(Error*)) {
178327c4aa55b33d3a3836cf70c8f7094bce1c5ead8cChris Masone  store_.RegisterDerivedStrings(
1784cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan      name, StringsAccessor(
1785cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan                new CustomAccessor<Manager, Strings>(this, get, nullptr)));
1786b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone}
1787b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone
17889d97b7deda3ae604d718873207a951f62d418b34Paul Stewartvoid Manager::HelpRegisterDerivedBool(
17898ae18741780300de3126826b72593391f2d00313Paul Stewart    const string& name,
17908ae18741780300de3126826b72593391f2d00313Paul Stewart    bool(Manager::*get)(Error* error),
17918ae18741780300de3126826b72593391f2d00313Paul Stewart    bool(Manager::*set)(const bool&, Error*)) {
17929d97b7deda3ae604d718873207a951f62d418b34Paul Stewart  store_.RegisterDerivedBool(
17939d97b7deda3ae604d718873207a951f62d418b34Paul Stewart      name,
1794cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan      BoolAccessor(new CustomAccessor<Manager, bool>(this, get, set, nullptr)));
17959d97b7deda3ae604d718873207a951f62d418b34Paul Stewart}
17969d97b7deda3ae604d718873207a951f62d418b34Paul Stewart
179722aa71b334c716f20999c2e08e5b797207b0afaePaul Stewartvoid Manager::SortServices() {
1798dfa46057cfb0a3af99d326694e2537f1189dcc06Paul Stewart  // We might be called in the middle of a series of events that
1799dfa46057cfb0a3af99d326694e2537f1189dcc06Paul Stewart  // may result in multiple calls to Manager::SortServices, or within
1800dfa46057cfb0a3af99d326694e2537f1189dcc06Paul Stewart  // an outer loop that may also be traversing the services_ list.
1801dfa46057cfb0a3af99d326694e2537f1189dcc06Paul Stewart  // Defer this work to the event loop.
1802dfa46057cfb0a3af99d326694e2537f1189dcc06Paul Stewart  if (sort_services_task_.IsCancelled()) {
1803dfa46057cfb0a3af99d326694e2537f1189dcc06Paul Stewart    sort_services_task_.Reset(Bind(&Manager::SortServicesTask, AsWeakPtr()));
1804dfa46057cfb0a3af99d326694e2537f1189dcc06Paul Stewart    dispatcher_->PostTask(sort_services_task_.callback());
1805dfa46057cfb0a3af99d326694e2537f1189dcc06Paul Stewart  }
1806dfa46057cfb0a3af99d326694e2537f1189dcc06Paul Stewart}
1807dfa46057cfb0a3af99d326694e2537f1189dcc06Paul Stewart
1808dfa46057cfb0a3af99d326694e2537f1189dcc06Paul Stewartvoid Manager::SortServicesTask() {
1809c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 4) << "In " << __func__;
1810dfa46057cfb0a3af99d326694e2537f1189dcc06Paul Stewart  sort_services_task_.Cancel();
1811a20cbc2864edf5491cfa1fa240ba83c30b8a483cThieu Le  ServiceRefPtr default_service;
1812a20cbc2864edf5491cfa1fa240ba83c30b8a483cThieu Le
1813c1dec4d5cad7c6ee2cd8dbc4f47e4d30403dcca1Paul Stewart  if (!services_.empty()) {
1814e2bad7c1edd7dbe837619e5350bd70814e6913bePaul Stewart    // Keep track of the service that is the candidate for the default
1815e2bad7c1edd7dbe837619e5350bd70814e6913bePaul Stewart    // service.  We have not yet tested to see if this service has a
1816e2bad7c1edd7dbe837619e5350bd70814e6913bePaul Stewart    // connection.
1817a20cbc2864edf5491cfa1fa240ba83c30b8a483cThieu Le    default_service = services_[0];
1818c1dec4d5cad7c6ee2cd8dbc4f47e4d30403dcca1Paul Stewart  }
181939db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart  const bool kCompareConnectivityState = true;
182039db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart  sort(services_.begin(), services_.end(),
18216d4836bd3e385b8929597c366b4d5ba969f5cd04Rebecca Silberstein       ServiceSorter(this, kCompareConnectivityState, technology_order_));
1822a41e38d57e4fa37bd2c8de6447890b4e1951acb7Paul Stewart
1823c1dec4d5cad7c6ee2cd8dbc4f47e4d30403dcca1Paul Stewart  if (!services_.empty()) {
1824a20cbc2864edf5491cfa1fa240ba83c30b8a483cThieu Le    ConnectionRefPtr default_connection = default_service->connection();
1825a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov    if (default_connection &&
1826a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov        services_[0]->connection() != default_connection) {
1827c1dec4d5cad7c6ee2cd8dbc4f47e4d30403dcca1Paul Stewart      default_connection->SetIsDefault(false);
1828c1dec4d5cad7c6ee2cd8dbc4f47e4d30403dcca1Paul Stewart    }
1829a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov    if (services_[0]->connection()) {
1830c1dec4d5cad7c6ee2cd8dbc4f47e4d30403dcca1Paul Stewart      services_[0]->connection()->SetIsDefault(true);
18318596f9f1341d3698543e1010ac1710cbe91e35d5Paul Stewart      if (default_service != services_[0]) {
18328596f9f1341d3698543e1010ac1710cbe91e35d5Paul Stewart        default_service = services_[0];
18338596f9f1341d3698543e1010ac1710cbe91e35d5Paul Stewart        LOG(INFO) << "Default service is now "
18348596f9f1341d3698543e1010ac1710cbe91e35d5Paul Stewart                  << default_service->unique_name();
18358596f9f1341d3698543e1010ac1710cbe91e35d5Paul Stewart      }
1836e2bad7c1edd7dbe837619e5350bd70814e6913bePaul Stewart    } else {
1837cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan      default_service = nullptr;
1838c1dec4d5cad7c6ee2cd8dbc4f47e4d30403dcca1Paul Stewart    }
1839c1dec4d5cad7c6ee2cd8dbc4f47e4d30403dcca1Paul Stewart  }
1840b4a9c9cba834a72a7b80ef27b273e7027aab134bmukesh agrawal
1841b4a9c9cba834a72a7b80ef27b273e7027aab134bmukesh agrawal  Error error;
184219a14db2ad2ea381ec30074fe2e53a619a97cd0cPaul Stewart  adaptor_->EmitRpcIdentifierArrayChanged(kServiceCompleteListProperty,
1843cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan                                          EnumerateCompleteServices(nullptr));
1844b4a9c9cba834a72a7b80ef27b273e7027aab134bmukesh agrawal  adaptor_->EmitRpcIdentifierArrayChanged(kServicesProperty,
1845cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan                                          EnumerateAvailableServices(nullptr));
1846b4a9c9cba834a72a7b80ef27b273e7027aab134bmukesh agrawal  adaptor_->EmitRpcIdentifierArrayChanged(kServiceWatchListProperty,
1847cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan                                          EnumerateWatchedServices(nullptr));
1848b4a9c9cba834a72a7b80ef27b273e7027aab134bmukesh agrawal  adaptor_->EmitStringsChanged(kConnectedTechnologiesProperty,
1849b4a9c9cba834a72a7b80ef27b273e7027aab134bmukesh agrawal                               ConnectedTechnologies(&error));
1850b4a9c9cba834a72a7b80ef27b273e7027aab134bmukesh agrawal  adaptor_->EmitStringChanged(kDefaultTechnologyProperty,
1851b4a9c9cba834a72a7b80ef27b273e7027aab134bmukesh agrawal                              DefaultTechnology(&error));
1852a5e07ef0402aad0635a5e7a0932740b9dfbf46d1Darin Petkov  NotifyDefaultServiceChanged(default_service);
185303e29f77413e978ecfbd46e51979916f6e7ebff8Paul Stewart  RefreshConnectionState();
18542cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart  DetectMultiHomedDevices();
1855b4a9c9cba834a72a7b80ef27b273e7027aab134bmukesh agrawal
18568a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal  AutoConnect();
18578a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal}
18588a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal
185994d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiuvoid Manager::DeviceStatusCheckTask() {
1860c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 4) << "In " << __func__;
186194d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu
186294d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu  ConnectionStatusCheck();
186394d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu  DevicePresenceStatusCheck();
186494d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu
186594d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu  dispatcher_->PostDelayedTask(device_status_check_task_.callback(),
186694d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu                               kDeviceStatusCheckIntervalMilliseconds);
186794d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu}
186894d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu
186994d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiuvoid Manager::ConnectionStatusCheck() {
1870c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 4) << "In " << __func__;
1871700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu  // Report current connection status.
1872700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu  Metrics::ConnectionStatus status = Metrics::kConnectionStatusOffline;
1873700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu  if (IsConnected()) {
1874700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu    status = Metrics::kConnectionStatusConnected;
1875700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu    // Check if device is online as well.
1876700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu    if (IsOnline()) {
1877700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu      metrics_->NotifyDeviceConnectionStatus(Metrics::kConnectionStatusOnline);
1878700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu    }
1879700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu  }
1880700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu  metrics_->NotifyDeviceConnectionStatus(status);
188194d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu}
1882700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu
188394d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiuvoid Manager::DevicePresenceStatusCheck() {
188494d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu  Error error;
188594d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu  vector<string> available_technologies = AvailableTechnologies(&error);
188694d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu
18878ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& technology : kProbeTechnologies) {
188894d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu    bool presence = std::find(available_technologies.begin(),
188994d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu                              available_technologies.end(),
189094d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu                              technology) != available_technologies.end();
189194d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu    metrics_->NotifyDevicePresenceStatus(
189294d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu        Technology::IdentifierFromName(technology), presence);
189394d18aff4f9f26e08929add6f5376f3df546d89ePeter Qiu  }
1894700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu}
1895700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu
18968ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::MatchProfileWithService(const ServiceRefPtr& service) {
18977522551440b9a287bccf2d95a42357d04ab79814Paul Stewart  vector<ProfileRefPtr>::reverse_iterator it;
18987522551440b9a287bccf2d95a42357d04ab79814Paul Stewart  for (it = profiles_.rbegin(); it != profiles_.rend(); ++it) {
18997522551440b9a287bccf2d95a42357d04ab79814Paul Stewart    if ((*it)->ConfigureService(service)) {
19007522551440b9a287bccf2d95a42357d04ab79814Paul Stewart      break;
19017522551440b9a287bccf2d95a42357d04ab79814Paul Stewart    }
19027522551440b9a287bccf2d95a42357d04ab79814Paul Stewart  }
19037522551440b9a287bccf2d95a42357d04ab79814Paul Stewart  if (it == profiles_.rend()) {
19047522551440b9a287bccf2d95a42357d04ab79814Paul Stewart    ephemeral_profile_->AdoptService(service);
19057522551440b9a287bccf2d95a42357d04ab79814Paul Stewart    return false;
19067522551440b9a287bccf2d95a42357d04ab79814Paul Stewart  }
19077522551440b9a287bccf2d95a42357d04ab79814Paul Stewart  return true;
19087522551440b9a287bccf2d95a42357d04ab79814Paul Stewart}
19097522551440b9a287bccf2d95a42357d04ab79814Paul Stewart
19108a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawalvoid Manager::AutoConnect() {
1911381a0bb9927ded7963004fcd6793a77a3fca327bSamuel Tan  if (suppress_autoconnect_) {
1912381a0bb9927ded7963004fcd6793a77a3fca327bSamuel Tan    LOG(INFO) << "Auto-connect suppressed -- explicitly suppressed.";
1913381a0bb9927ded7963004fcd6793a77a3fca327bSamuel Tan    return;
1914381a0bb9927ded7963004fcd6793a77a3fca327bSamuel Tan  }
191563864b6e7bda0e417d18093892ca1692ae926fe6Paul Stewart  if (!running_) {
191663864b6e7bda0e417d18093892ca1692ae926fe6Paul Stewart    LOG(INFO) << "Auto-connect suppressed -- not running.";
191763864b6e7bda0e417d18093892ca1692ae926fe6Paul Stewart    return;
191863864b6e7bda0e417d18093892ca1692ae926fe6Paul Stewart  }
1919787a1cebf2452c14bf392ab99902e686ea4a6fb4Samuel Tan  if (power_manager_ && power_manager_->suspending() &&
1920787a1cebf2452c14bf392ab99902e686ea4a6fb4Samuel Tan      !power_manager_->in_dark_resume()) {
1921fac0953b10f3c13f47ecd588c0f9a0382bc32776Daniel Erat    LOG(INFO) << "Auto-connect suppressed -- system is suspending.";
1922ca62154261be3d481c1e54d5fcf7012e8918b4e2Darin Petkov    return;
1923ca62154261be3d481c1e54d5fcf7012e8918b4e2Darin Petkov  }
19248a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal  if (services_.empty()) {
1925ca62154261be3d481c1e54d5fcf7012e8918b4e2Darin Petkov    LOG(INFO) << "Auto-connect suppressed -- no services.";
19268a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal    return;
19278a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal  }
19288a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal
1929fad4a0b7e55dd82d3815ee96862b6e546727eb6eBen Chan  if (SLOG_IS_ON(Manager, 4)) {
1930c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein    SLOG(this, 4) << "Sorted service list for AutoConnect: ";
1931ddc378f1b63b842cc691ecd2274c3674525a7639mukesh agrawal    for (size_t i = 0; i < services_.size(); ++i) {
1932ddc378f1b63b842cc691ecd2274c3674525a7639mukesh agrawal      ServiceRefPtr service = services_[i];
19338ae18741780300de3126826b72593391f2d00313Paul Stewart      const char* compare_reason = nullptr;
1934ddc378f1b63b842cc691ecd2274c3674525a7639mukesh agrawal      if (i + 1 < services_.size()) {
193539db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart        const bool kCompareConnectivityState = true;
1936ddc378f1b63b842cc691ecd2274c3674525a7639mukesh agrawal        Service::Compare(
1937fe734676357045eab81ab62fc3ea7ae1a40ed905Samuel Tan            this, service, services_[i+1], kCompareConnectivityState,
1938fe734676357045eab81ab62fc3ea7ae1a40ed905Samuel Tan            technology_order_, &compare_reason);
1939ddc378f1b63b842cc691ecd2274c3674525a7639mukesh agrawal      } else {
1940bf14e94cbd47d6320eec846f1ca4def026840e14mukesh agrawal        compare_reason = "last";
1941ddc378f1b63b842cc691ecd2274c3674525a7639mukesh agrawal      }
1942c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein      SLOG(this, 4) << "Service " << service->unique_name()
1943c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " Profile: " << service->profile()->GetFriendlyName()
1944c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " IsConnected: " << service->IsConnected()
1945c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " IsConnecting: " << service->IsConnecting()
1946c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " HasEverConnected: " << service->has_ever_connected()
1947c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " IsFailed: " << service->IsFailed()
1948c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " connectable: " << service->connectable()
1949c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " auto_connect: " << service->auto_connect()
1950c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " retain_auto_connect: "
1951c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << service->retain_auto_connect()
1952c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " priority: " << service->priority()
1953c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " crypto_algorithm: " << service->crypto_algorithm()
1954c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " key_rotation: " << service->key_rotation()
1955c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " endpoint_auth: " << service->endpoint_auth()
1956c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " strength: " << service->strength()
1957c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " sorted: " << compare_reason;
19588a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal    }
19598a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal  }
19608a3188dbc04245c17a4729d16a632547ce4bf585mukesh agrawal
19611a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIFI)
1962574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu  // Report the number of auto-connectable wifi services available when wifi is
1963574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu  // idle (no active or pending connection), which will trigger auto connect
1964574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu  // for wifi services.
1965574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu  if (IsWifiIdle()) {
1966574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu    wifi_provider_->ReportAutoConnectableServices();
1967574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu  }
19681a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif  // DISABLE_WIFI
1969574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu
19703d9bcf58bd29080b96db4a2c9e7bfe6ed3d6e6dfPaul Stewart  // Perform auto-connect.
19718ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_) {
19726db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (service->auto_connect()) {
19736db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart      service->AutoConnect();
19743d9bcf58bd29080b96db4a2c9e7bfe6ed3d6e6dfPaul Stewart    }
19753d9bcf58bd29080b96db4a2c9e7bfe6ed3d6e6dfPaul Stewart  }
197622aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart}
197722aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart
19788ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::ConnectToBestServices(Error* /*error*/) {
197939db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart  dispatcher_->PostTask(Bind(&Manager::ConnectToBestServicesTask, AsWeakPtr()));
198039db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart}
198139db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart
198239db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewartvoid Manager::ConnectToBestServicesTask() {
198339db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart  vector<ServiceRefPtr> services_copy = services_;
198439db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart  const bool kCompareConnectivityState = false;
198539db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart  sort(services_copy.begin(), services_copy.end(),
19866d4836bd3e385b8929597c366b4d5ba969f5cd04Rebecca Silberstein       ServiceSorter(this, kCompareConnectivityState, technology_order_));
198739db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart  set<Technology::Identifier> connecting_technologies;
19888ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_copy) {
19896db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (!service->connectable()) {
199039db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      // Due to service sort order, it is guaranteed that no services beyond
199139db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      // this one will be connectable either.
199239db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      break;
199339db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart    }
19946db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (!service->auto_connect() || !service->IsVisible()) {
199539db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      continue;
199639db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart    }
19976db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    Technology::Identifier technology = service->technology();
199839db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart    if (!Technology::IsPrimaryConnectivityTechnology(technology) &&
1999700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu        !IsConnected()) {
200039db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      // Non-primary services need some other service connected first.
200139db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      continue;
200239db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart    }
200339db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart    if (ContainsKey(connecting_technologies, technology)) {
200439db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      // We have already started a connection for this technology.
200539db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      continue;
200639db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart    }
20076db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (service->explicitly_disconnected())
20086fe4f26613956552aa2016337659cd9bca55b8e5Arman Uguray      continue;
200939db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart    connecting_technologies.insert(technology);
20106db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (!service->IsConnected() && !service->IsConnecting()) {
201139db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      // At first blush, it may seem that using Service::AutoConnect might
201239db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      // be the right choice, however Service::IsAutoConnectable and its
201339db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      // overridden implementations consider a host of conditions which
201439db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      // prevent it from attempting a connection which we'd like to ignore
201539db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      // for the purposes of this user-initiated action.
201639db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      Error error;
20176db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart      service->Connect(&error, __func__);
201839db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      if (error.IsFailure()) {
201939db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart        LOG(ERROR) << "Connection failed: " << error.message();
202039db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart      }
202139db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart    }
202239db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart  }
2023ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein
2024ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein  if (SLOG_IS_ON(Manager, 4)) {
2025c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein    SLOG(this, 4) << "Sorted service list for ConnectToBestServicesTask: ";
2026ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein    for (size_t i = 0; i < services_copy.size(); ++i) {
2027ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein      ServiceRefPtr service = services_copy[i];
20288ae18741780300de3126826b72593391f2d00313Paul Stewart      const char* compare_reason = nullptr;
2029ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein      if (i + 1 < services_copy.size()) {
2030ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein        if (!service->connectable()) {
2031ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein          // Due to service sort order, it is guaranteed that no services beyond
2032ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein          // this one are connectable either.
2033ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein          break;
2034ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein        }
2035ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein        Service::Compare(
2036ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein            this, service, services_copy[i+1],
2037ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein            kCompareConnectivityState, technology_order_,
2038ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein            &compare_reason);
2039ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein      } else {
2040ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein        compare_reason = "last";
2041ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein      }
2042c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein      SLOG(this, 4) << "Service " << service->unique_name()
2043c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " Profile: " << service->profile()->GetFriendlyName()
2044c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " IsConnected: " << service->IsConnected()
2045c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " IsConnecting: " << service->IsConnecting()
2046c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " HasEverConnected: " << service->has_ever_connected()
2047c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " IsFailed: " << service->IsFailed()
2048c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " connectable: " << service->connectable()
2049c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " auto_connect: " << service->auto_connect()
2050c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " retain_auto_connect: "
2051c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << service->retain_auto_connect()
2052c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " priority: " << service->priority()
2053c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " crypto_algorithm: " << service->crypto_algorithm()
2054c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " key_rotation: " << service->key_rotation()
2055c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " endpoint_auth: " << service->endpoint_auth()
2056c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " strength: " << service->strength()
2057c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << " sorted: " << compare_reason;
2058ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein    }
2059ae11f590d7a097a610d91a8e0ddeefa7fcd80403Rebecca Silberstein  }
206039db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart}
206139db5caaa3d07c3af9c575affcbb7313536de91dPaul Stewart
20628ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::CreateConnectivityReport(Error* /*error*/) {
2063f4365a68767063e87dc7f68ff24b6c3955e88c5dRebecca Silberstein  LOG(INFO) << "Creating Connectivity Report";
2064f4365a68767063e87dc7f68ff24b6c3955e88c5dRebecca Silberstein
20656862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein  // For each of the connected services, perform a single portal detection
20666862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein  // test to assess connectivity.  The results should be written to the log.
20678ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_) {
20686862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein    if (!service->IsConnected()) {
20696862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein      // Service sort order guarantees that no service beyond this one will be
20706862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein      // connected either.
20716862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein      break;
20726862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein    }
20736862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein    // Get the underlying device for this service and perform connectivity test.
20748ae18741780300de3126826b72593391f2d00313Paul Stewart    for (const auto& device : devices_) {
20756862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein      if (device->IsConnectedToService(service)) {
20766862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein        if (device->StartConnectivityTest()) {
2077c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein          SLOG(this, 3) << "Started connectivity test for service "
2078c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                        << service->unique_name();
20796862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein        } else {
2080c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein          SLOG(this, 3) << "Failed to start connectivity test for service "
2081c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                        << service->unique_name()
20826862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein                           << " device not reporting IsConnected.";
20836862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein        }
20846862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein        break;
20856862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein      }
20866862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein    }
20876862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein  }
20886862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein}
20896862b38f4691f6f927a5efffa3f587846ff96c72Rebecca Silberstein
2090700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiubool Manager::IsConnected() const {
2091028545d00919bac838b8c8f691b799db6bb93de5Gary Morain  // |services_| is sorted such that connected services are first.
20924cbff5b5897593f7a2e6de48a98abe72356075afDarin Petkov  return !services_.empty() && services_.front()->IsConnected();
20934cbff5b5897593f7a2e6de48a98abe72356075afDarin Petkov}
20944cbff5b5897593f7a2e6de48a98abe72356075afDarin Petkov
2095700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiubool Manager::IsOnline() const {
2096700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu  // |services_| is sorted such that online services are first.
2097700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu  return !services_.empty() && services_.front()->IsOnline();
2098700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu}
2099700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu
21008ae18741780300de3126826b72593391f2d00313Paul Stewartstring Manager::CalculateState(Error* /*error*/) {
2101700de6400c18f8cba77821f8cd2a1935b96999a6Peter Qiu  return IsConnected() ? kStateOnline : kStateOffline;
2102b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone}
2103b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone
210403e29f77413e978ecfbd46e51979916f6e7ebff8Paul Stewartvoid Manager::RefreshConnectionState() {
21058ae18741780300de3126826b72593391f2d00313Paul Stewart  const ServiceRefPtr& service = GetDefaultService();
210603e29f77413e978ecfbd46e51979916f6e7ebff8Paul Stewart  string connection_state = service ? service->GetStateString() : kStateIdle;
210703e29f77413e978ecfbd46e51979916f6e7ebff8Paul Stewart  if (connection_state_ == connection_state) {
210803e29f77413e978ecfbd46e51979916f6e7ebff8Paul Stewart    return;
210903e29f77413e978ecfbd46e51979916f6e7ebff8Paul Stewart  }
211003e29f77413e978ecfbd46e51979916f6e7ebff8Paul Stewart  connection_state_ = connection_state;
211103e29f77413e978ecfbd46e51979916f6e7ebff8Paul Stewart  adaptor_->EmitStringChanged(kConnectionStateProperty, connection_state_);
21122b35cfb222200f9d7bac73f68038e9126146ae5eRoshan Pius  // Send upstart notifications for the initial idle state
21132b35cfb222200f9d7bac73f68038e9126146ae5eRoshan Pius  // and when we transition in/out of connected states.
21142b35cfb222200f9d7bac73f68038e9126146ae5eRoshan Pius  if ((!is_connected_state_) && (IsConnected())) {
21152b35cfb222200f9d7bac73f68038e9126146ae5eRoshan Pius      is_connected_state_ = true;
21162b35cfb222200f9d7bac73f68038e9126146ae5eRoshan Pius      upstart_->NotifyConnected();
21172b35cfb222200f9d7bac73f68038e9126146ae5eRoshan Pius  } else if ((is_connected_state_) && (!IsConnected())) {
21182b35cfb222200f9d7bac73f68038e9126146ae5eRoshan Pius      is_connected_state_ = false;
21192b35cfb222200f9d7bac73f68038e9126146ae5eRoshan Pius      upstart_->NotifyDisconnected();
21202b35cfb222200f9d7bac73f68038e9126146ae5eRoshan Pius  } else if (connection_state_ == kStateIdle) {
212159a8cba0d9763ffd5199fba4dc898e5c16aae871Paul Stewart      upstart_->NotifyDisconnected();
212259a8cba0d9763ffd5199fba4dc898e5c16aae871Paul Stewart  }
212303e29f77413e978ecfbd46e51979916f6e7ebff8Paul Stewart}
212403e29f77413e978ecfbd46e51979916f6e7ebff8Paul Stewart
21258ae18741780300de3126826b72593391f2d00313Paul Stewartvector<string> Manager::AvailableTechnologies(Error* /*error*/) {
2126435de2cd55a95836381b53acbce8cbbad98ec04dGaurav Shah  set<string> unique_technologies;
21278ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
2128435de2cd55a95836381b53acbce8cbbad98ec04dGaurav Shah    unique_technologies.insert(
21296db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart        Technology::NameFromIdentifier(device->technology()));
2130435de2cd55a95836381b53acbce8cbbad98ec04dGaurav Shah  }
2131435de2cd55a95836381b53acbce8cbbad98ec04dGaurav Shah  return vector<string>(unique_technologies.begin(), unique_technologies.end());
2132b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone}
2133b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone
21348ae18741780300de3126826b72593391f2d00313Paul Stewartvector<string> Manager::ConnectedTechnologies(Error* /*error*/) {
2135435de2cd55a95836381b53acbce8cbbad98ec04dGaurav Shah  set<string> unique_technologies;
21368ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
21376db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (device->IsConnected())
2138435de2cd55a95836381b53acbce8cbbad98ec04dGaurav Shah      unique_technologies.insert(
21396db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart          Technology::NameFromIdentifier(device->technology()));
2140435de2cd55a95836381b53acbce8cbbad98ec04dGaurav Shah  }
2141435de2cd55a95836381b53acbce8cbbad98ec04dGaurav Shah  return vector<string>(unique_technologies.begin(), unique_technologies.end());
2142b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone}
2143b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone
21443c5040174273386868cc8dea8044d22c465885d8Paul Stewartbool Manager::IsTechnologyConnected(Technology::Identifier technology) const {
21458ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
21466db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (device->technology() == technology && device->IsConnected())
21473c5040174273386868cc8dea8044d22c465885d8Paul Stewart      return true;
21483c5040174273386868cc8dea8044d22c465885d8Paul Stewart  }
21493c5040174273386868cc8dea8044d22c465885d8Paul Stewart  return false;
21503c5040174273386868cc8dea8044d22c465885d8Paul Stewart}
21513c5040174273386868cc8dea8044d22c465885d8Paul Stewart
21528ae18741780300de3126826b72593391f2d00313Paul Stewartstring Manager::DefaultTechnology(Error* /*error*/) {
2153435de2cd55a95836381b53acbce8cbbad98ec04dGaurav Shah  return (!services_.empty() && services_[0]->IsConnected()) ?
215458f0b6dbd71f52c3abdac91aed44024a35bc4898Darin Petkov      services_[0]->GetTechnologyString() : "";
2155b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone}
2156b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone
21578ae18741780300de3126826b72593391f2d00313Paul Stewartvector<string> Manager::EnabledTechnologies(Error* /*error*/) {
21589a24553461df7036755060423f90804011612249Eric Shienbrood  set<string> unique_technologies;
21598ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
21606db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (device->enabled())
21619a24553461df7036755060423f90804011612249Eric Shienbrood      unique_technologies.insert(
21626db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart          Technology::NameFromIdentifier(device->technology()));
21639a24553461df7036755060423f90804011612249Eric Shienbrood  }
21649a24553461df7036755060423f90804011612249Eric Shienbrood  return vector<string>(unique_technologies.begin(), unique_technologies.end());
2165b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone}
2166b925cc8f481d21fddd9569fc68861f6e5b6e3eaeChris Masone
21678ae18741780300de3126826b72593391f2d00313Paul Stewartvector<string> Manager::UninitializedTechnologies(Error* /*error*/) {
21685086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan  return device_info_.GetUninitializedTechnologies();
21695086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan}
21705086b9744e8330e7f3bd8ab91fe20b53dda28a1cBen Chan
21718ae18741780300de3126826b72593391f2d00313Paul StewartRpcIdentifiers Manager::EnumerateDevices(Error* /*error*/) {
2172cb3eb8970ee676be0e5738d62685f9e0a2d7cb73Paul Stewart  RpcIdentifiers device_rpc_ids;
21738ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
21746db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    device_rpc_ids.push_back(device->GetRpcIdentifier());
21753c3f6a1dcc0533545f7efb5ffed5a3edc089f240Chris Masone  }
21768e60d61b13fedf9cb75f1d4f1762605375837d98Peter Qiu  // Enumerate devices that are internal to the services, such as PPPoE devices.
21778e60d61b13fedf9cb75f1d4f1762605375837d98Peter Qiu  for (const auto& service : services_) {
21788e60d61b13fedf9cb75f1d4f1762605375837d98Peter Qiu    if (!service->GetInnerDeviceRpcIdentifier().empty()) {
21798e60d61b13fedf9cb75f1d4f1762605375837d98Peter Qiu      device_rpc_ids.push_back(service->GetInnerDeviceRpcIdentifier());
21808e60d61b13fedf9cb75f1d4f1762605375837d98Peter Qiu    }
21818e60d61b13fedf9cb75f1d4f1762605375837d98Peter Qiu  }
21823c3f6a1dcc0533545f7efb5ffed5a3edc089f240Chris Masone  return device_rpc_ids;
21833c3f6a1dcc0533545f7efb5ffed5a3edc089f240Chris Masone}
21843c3f6a1dcc0533545f7efb5ffed5a3edc089f240Chris Masone
21858ae18741780300de3126826b72593391f2d00313Paul StewartRpcIdentifiers Manager::EnumerateProfiles(Error* /*error*/) {
2186cb3eb8970ee676be0e5738d62685f9e0a2d7cb73Paul Stewart  RpcIdentifiers profile_rpc_ids;
21878ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& profile : profiles_) {
21886db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    profile_rpc_ids.push_back(profile->GetRpcIdentifier());
21891b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart  }
21901b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart  return profile_rpc_ids;
21911b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart}
21921b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart
21938ae18741780300de3126826b72593391f2d00313Paul StewartRpcIdentifiers Manager::EnumerateAvailableServices(Error* /*error*/) {
219419a14db2ad2ea381ec30074fe2e53a619a97cd0cPaul Stewart  RpcIdentifiers service_rpc_ids;
21958ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_) {
21966db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (service->IsVisible()) {
21976db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart      service_rpc_ids.push_back(service->GetRpcIdentifier());
2198bfb825563ecdf282162dfb4e43ded89c99b0fbb5Paul Stewart    }
21993c3f6a1dcc0533545f7efb5ffed5a3edc089f240Chris Masone  }
22003c3f6a1dcc0533545f7efb5ffed5a3edc089f240Chris Masone  return service_rpc_ids;
22013c3f6a1dcc0533545f7efb5ffed5a3edc089f240Chris Masone}
22023c3f6a1dcc0533545f7efb5ffed5a3edc089f240Chris Masone
22038ae18741780300de3126826b72593391f2d00313Paul StewartRpcIdentifiers Manager::EnumerateCompleteServices(Error* /*error*/) {
220419a14db2ad2ea381ec30074fe2e53a619a97cd0cPaul Stewart  RpcIdentifiers service_rpc_ids;
22058ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_) {
22066db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    service_rpc_ids.push_back(service->GetRpcIdentifier());
22073c5040174273386868cc8dea8044d22c465885d8Paul Stewart  }
22083c5040174273386868cc8dea8044d22c465885d8Paul Stewart  return service_rpc_ids;
22093c5040174273386868cc8dea8044d22c465885d8Paul Stewart}
22103c5040174273386868cc8dea8044d22c465885d8Paul Stewart
22118ae18741780300de3126826b72593391f2d00313Paul StewartRpcIdentifiers Manager::EnumerateWatchedServices(Error* /*error*/) {
221219a14db2ad2ea381ec30074fe2e53a619a97cd0cPaul Stewart  RpcIdentifiers service_rpc_ids;
2213220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart  watched_service_states_.clear();
22148ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_) {
2215cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan    if (service->IsVisible() && service->IsActive(nullptr)) {
22166db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart      service_rpc_ids.push_back(service->GetRpcIdentifier());
2217220ae4e84acc9c7edead58c719b727b5fea925ffPaul Stewart      watched_service_states_[service->unique_name()] = service->state();
2218bfb825563ecdf282162dfb4e43ded89c99b0fbb5Paul Stewart    }
2219bfb825563ecdf282162dfb4e43ded89c99b0fbb5Paul Stewart  }
2220bfb825563ecdf282162dfb4e43ded89c99b0fbb5Paul Stewart  return service_rpc_ids;
22213c3f6a1dcc0533545f7efb5ffed5a3edc089f240Chris Masone}
22223c3f6a1dcc0533545f7efb5ffed5a3edc089f240Chris Masone
22238ae18741780300de3126826b72593391f2d00313Paul Stewartstring Manager::GetActiveProfileRpcIdentifier(Error* /*error*/) {
22241b2531423a15ccc5ac5acaf09edac9a687902dfaPaul Stewart  return ActiveProfile()->GetRpcIdentifier();
22257aa5f90848b530999d8b6788ecb40aa30871c7aeChris Masone}
22267aa5f90848b530999d8b6788ecb40aa30871c7aeChris Masone
22278ae18741780300de3126826b72593391f2d00313Paul Stewartstring Manager::GetCheckPortalList(Error* /*error*/) {
2228df7c553368620f718ec14bc6751f232185792870Jason Glasgow  return use_startup_portal_list_ ? startup_portal_list_ :
2229df7c553368620f718ec14bc6751f232185792870Jason Glasgow      props_.check_portal_list;
223010e9e4e93537a0673524d47535cbf0f723470a0dPaul Stewart}
223110e9e4e93537a0673524d47535cbf0f723470a0dPaul Stewart
22328ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::SetCheckPortalList(const string& portal_list, Error* error) {
223310e9e4e93537a0673524d47535cbf0f723470a0dPaul Stewart  use_startup_portal_list_ = false;
2234bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  if (props_.check_portal_list == portal_list) {
2235bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal    return false;
2236bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  }
2237bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  props_.check_portal_list = portal_list;
2238bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  return true;
223910e9e4e93537a0673524d47535cbf0f723470a0dPaul Stewart}
224010e9e4e93537a0673524d47535cbf0f723470a0dPaul Stewart
22418ae18741780300de3126826b72593391f2d00313Paul Stewartstring Manager::GetIgnoredDNSSearchPaths(Error* /*error*/) {
22424d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart  return props_.ignored_dns_search_paths;
22434d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart}
22444d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart
22458ae18741780300de3126826b72593391f2d00313Paul Stewartbool Manager::SetIgnoredDNSSearchPaths(const string& ignored_paths,
22468ae18741780300de3126826b72593391f2d00313Paul Stewart                                       Error* /*error*/) {
2247bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  if (props_.ignored_dns_search_paths == ignored_paths) {
2248bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal    return false;
2249bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  }
22504d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart  vector<string> ignored_path_list;
22514d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart  if (!ignored_paths.empty()) {
22523a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko    ignored_path_list = base::SplitString(
22533a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko        ignored_paths, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
22544d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart  }
2255bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  props_.ignored_dns_search_paths = ignored_paths;
22564d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart  resolver_->set_ignored_search_list(ignored_path_list);
2257bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal  return true;
22584d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart}
22594d5efb7d5d130e3e6e52ab732127a273bcb95261Paul Stewart
22603239932e4a0a92fec52d88860081cbbb003eabb0mukesh agrawal// called via RPC (e.g., from ManagerDBusAdaptor)
22618ae18741780300de3126826b72593391f2d00313Paul StewartServiceRefPtr Manager::GetService(const KeyValueStore& args, Error* error) {
2262923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  if (args.ContainsString(kTypeProperty) &&
2263923a5025a5e1138b052cbeffa60ea387d479696fBen Chan      args.GetString(kTypeProperty) == kTypeVPN) {
22647f5ad57031c51938d29206e60a7d26df719887a8Paul Stewart     // GetService on a VPN service should actually perform ConfigureService.
22657f5ad57031c51938d29206e60a7d26df719887a8Paul Stewart     // TODO(pstew): Remove this hack and change Chrome to use ConfigureService
2266ee6b3d7f9d49fa52072a352fbb59f06127b1ba4cPaul Stewart     // instead, when we no longer need to support flimflam.  crbug.com/213802
22677f5ad57031c51938d29206e60a7d26df719887a8Paul Stewart     return ConfigureService(args, error);
22687f5ad57031c51938d29206e60a7d26df719887a8Paul Stewart  }
22692c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart
22702c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart  ServiceRefPtr service = GetServiceInner(args, error);
22712c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart  if (service) {
22722c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart    // Configures the service using the rest of the passed-in arguments.
22732c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart    service->Configure(args, error);
22742c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart  }
22752c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart
22762c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart  return service;
22777f5ad57031c51938d29206e60a7d26df719887a8Paul Stewart}
22787f5ad57031c51938d29206e60a7d26df719887a8Paul Stewart
22798ae18741780300de3126826b72593391f2d00313Paul StewartServiceRefPtr Manager::GetServiceInner(const KeyValueStore& args,
22808ae18741780300de3126826b72593391f2d00313Paul Stewart                                       Error* error) {
2281923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  if (args.ContainsString(kGuidProperty)) {
2282c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein    SLOG(this, 2) << __func__ << ": searching by GUID";
228313ed225b4a4567e8e2411435d1266c8b86236c54Paul Stewart    ServiceRefPtr service =
2284cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan        GetServiceWithGUID(args.GetString(kGuidProperty), nullptr);
228513ed225b4a4567e8e2411435d1266c8b86236c54Paul Stewart    if (service) {
228613ed225b4a4567e8e2411435d1266c8b86236c54Paul Stewart      return service;
228713ed225b4a4567e8e2411435d1266c8b86236c54Paul Stewart    }
228813ed225b4a4567e8e2411435d1266c8b86236c54Paul Stewart  }
228913ed225b4a4567e8e2411435d1266c8b86236c54Paul Stewart
2290923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  if (!args.ContainsString(kTypeProperty)) {
229134f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(
229234f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart        FROM_HERE, error, Error::kInvalidArguments, kErrorTypeRequired);
2293cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan    return nullptr;
2294b65c24574109b331150f376f117e10948acc7123Darin Petkov  }
2295b65c24574109b331150f376f117e10948acc7123Darin Petkov
2296923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  string type = args.GetString(kTypeProperty);
2297b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart  Technology::Identifier technology = Technology::IdentifierFromName(type);
2298b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart  if (!ContainsKey(providers_, technology)) {
229934f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
2300b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart                          kErrorUnsupportedServiceType);
2301cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan    return nullptr;
2302b65c24574109b331150f376f117e10948acc7123Darin Petkov  }
2303b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart
2304c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << __func__ << ": getting " << type << " Service";
2305b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart  return providers_[technology]->GetService(args, error);
2306b65c24574109b331150f376f117e10948acc7123Darin Petkov}
2307b65c24574109b331150f376f117e10948acc7123Darin Petkov
23087f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart// called via RPC (e.g., from ManagerDBusAdaptor)
23098ae18741780300de3126826b72593391f2d00313Paul StewartServiceRefPtr Manager::ConfigureService(const KeyValueStore& args,
23108ae18741780300de3126826b72593391f2d00313Paul Stewart                                        Error* error) {
23117f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  ProfileRefPtr profile = ActiveProfile();
2312923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  bool profile_specified = args.ContainsString(kProfileProperty);
23137f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  if (profile_specified) {
2314923a5025a5e1138b052cbeffa60ea387d479696fBen Chan    string profile_rpcid = args.GetString(kProfileProperty);
23157f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart    profile = LookupProfileByRpcIdentifier(profile_rpcid);
23167f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart    if (!profile) {
231734f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart      Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
23187f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart                            "Invalid profile name " + profile_rpcid);
2319cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan      return nullptr;
23207f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart    }
23217f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  }
23227f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart
23237f5ad57031c51938d29206e60a7d26df719887a8Paul Stewart  ServiceRefPtr service = GetServiceInner(args, error);
23247f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  if (error->IsFailure() || !service) {
23257f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart    LOG(ERROR) << "GetService failed; returning upstream error.";
2326cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan    return nullptr;
23277f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  }
23287f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart
23292c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart  // First pull in any stored configuration associated with the service.
23302c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart  if (service->profile() == profile) {
2331c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein    SLOG(this, 2) << __func__ << ": service " << service->unique_name()
2332c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                  << " is already a member of profile "
23332c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart                     << profile->GetFriendlyName()
23342c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart                     << " so a load is not necessary.";
23352c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart  } else if (profile->LoadService(service)) {
2336c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein    SLOG(this, 2) << __func__ << ": applied stored information from profile "
2337c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                  << profile->GetFriendlyName()
2338c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                  << " into service "
2339c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                  << service->unique_name();
23402c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart  } else {
2341c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein    SLOG(this, 2) << __func__ << ": no previous information in profile "
2342c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                  << profile->GetFriendlyName()
2343c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                  << " exists for service "
2344c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                  << service->unique_name();
23452c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart  }
23462c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart
23472c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart  // Overlay this with the passed-in configuration parameters.
23482c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart  service->Configure(args, error);
23492c575d24aae064efe7c52566a8c07da72e6d2a7bPaul Stewart
235006175d70a09135fa0bac045807bca87c3c142289mukesh agrawal  // Overwrite the profile data with the resulting configured service.
23517f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  if (!profile->UpdateService(service)) {
235234f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError,
23537f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart                          "Unable to save service to profile");
2354cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan    return nullptr;
23557f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  }
23567f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart
23577f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  if (HasService(service)) {
23587f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart    // If the service has been registered (it may not be -- as is the case
23597f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart    // with invisible WiFi networks), we can now transfer the service between
23607f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart    // profiles.
236110ccbb3c6bc4f4246105743c8508fc9ce8759c17Paul Stewart    if (IsServiceEphemeral(service) ||
23627f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart        (profile_specified && service->profile() != profile)) {
2363c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein      SLOG(this, 2) << "Moving service to profile "
2364c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                    << profile->GetFriendlyName();
23657f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart      if (!MoveServiceToProfile(service, profile)) {
236634f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart        Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError,
23677f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart                              "Unable to move service to profile");
23687f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart      }
23697f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart    }
23707f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart  }
23714357f4ea204e5d3e7632d67f26531e106dd211e2Paul Stewart
23724357f4ea204e5d3e7632d67f26531e106dd211e2Paul Stewart  // Notify the service that a profile has been configured for it.
23734357f4ea204e5d3e7632d67f26531e106dd211e2Paul Stewart  service->OnProfileConfigured();
23747f5ad57031c51938d29206e60a7d26df719887a8Paul Stewart
23757f5ad57031c51938d29206e60a7d26df719887a8Paul Stewart  return service;
23767f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart}
23777f61e52dced33bd4cd5af1c7989ee6e59bf8f892Paul Stewart
2378d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart// called via RPC (e.g., from ManagerDBusAdaptor)
2379d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul StewartServiceRefPtr Manager::ConfigureServiceForProfile(
23808ae18741780300de3126826b72593391f2d00313Paul Stewart    const string& profile_rpcid, const KeyValueStore& args, Error* error) {
2381923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  if (!args.ContainsString(kTypeProperty)) {
238234f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(
238334f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart        FROM_HERE, error, Error::kInvalidArguments, kErrorTypeRequired);
2384cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan    return nullptr;
23856ae05893dd7b3c86e0c8a79b498fe0cd96deda59Paul Stewart  }
23866ae05893dd7b3c86e0c8a79b498fe0cd96deda59Paul Stewart
2387923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  string type = args.GetString(kTypeProperty);
23886ae05893dd7b3c86e0c8a79b498fe0cd96deda59Paul Stewart  Technology::Identifier technology = Technology::IdentifierFromName(type);
23896ae05893dd7b3c86e0c8a79b498fe0cd96deda59Paul Stewart
23906ae05893dd7b3c86e0c8a79b498fe0cd96deda59Paul Stewart  if (!ContainsKey(providers_, technology)) {
239134f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
23926ae05893dd7b3c86e0c8a79b498fe0cd96deda59Paul Stewart                          kErrorUnsupportedServiceType);
2393cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan    return nullptr;
2394d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  }
2395d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart
23968ae18741780300de3126826b72593391f2d00313Paul Stewart  ProviderInterface* provider = providers_[technology];
23976ae05893dd7b3c86e0c8a79b498fe0cd96deda59Paul Stewart
2398d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  ProfileRefPtr profile = LookupProfileByRpcIdentifier(profile_rpcid);
2399d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  if (!profile) {
240034f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kNotFound,
2401d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart                          "Profile specified was not found");
2402cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan    return nullptr;
2403d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  }
2404923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  if (args.LookupString(kProfileProperty, profile_rpcid) != profile_rpcid) {
240534f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
2406d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart                          "Profile argument does not match that in "
2407d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart                          "the configuration arguments");
2408cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan    return nullptr;
2409d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  }
2410d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart
2411d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  ServiceRefPtr service;
2412923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  if (args.ContainsString(kGuidProperty)) {
2413c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein    SLOG(this, 2) << __func__ << ": searching by GUID";
2414cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan    service = GetServiceWithGUID(args.GetString(kGuidProperty), nullptr);
24156ae05893dd7b3c86e0c8a79b498fe0cd96deda59Paul Stewart    if (service && service->technology() != technology) {
241634f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart      Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
24176ae05893dd7b3c86e0c8a79b498fe0cd96deda59Paul Stewart                            StringPrintf("This GUID matches a non-%s service",
24186ae05893dd7b3c86e0c8a79b498fe0cd96deda59Paul Stewart                                         type.c_str()));
2419cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan      return nullptr;
2420d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart    }
2421d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  }
2422d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart
2423d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  if (!service) {
2424d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart    Error find_error;
24256ae05893dd7b3c86e0c8a79b498fe0cd96deda59Paul Stewart    service = provider->FindSimilarService(args, &find_error);
2426d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  }
2427d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart
2428d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // If no matching service exists, create a new service in the specified
2429d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // profile using ConfigureService().
2430d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  if (!service) {
2431d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart    KeyValueStore configure_args;
2432d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart    configure_args.CopyFrom(args);
2433923a5025a5e1138b052cbeffa60ea387d479696fBen Chan    configure_args.SetString(kProfileProperty, profile_rpcid);
2434d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart    return ConfigureService(configure_args, error);
2435d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  }
2436d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart
2437d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // The service already exists and is set to the desired profile,
2438d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // the service is in the ephemeral profile, or the current profile
2439d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // for the service appears before the desired profile, we need to
2440d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // reassign the service to the new profile if necessary, leaving
2441d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // the old profile intact (i.e, not calling Profile::AbandonService()).
2442d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // Then, configure the properties on the service as well as its newly
2443d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // associated profile.
2444d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  if (service->profile() == profile ||
2445d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart      IsServiceEphemeral(service) ||
2446d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart      IsProfileBefore(service->profile(), profile)) {
2447d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart    SetupServiceInProfile(service, profile, args, error);
2448d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart    return service;
2449d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  }
2450d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart
2451d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // The current profile for the service appears after the desired
2452d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // profile.  We must create a temporary service specifically for
2453d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // the task of creating configuration data.  This service will
2454d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // neither inherit properties from the visible service, nor will
2455d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // it exist after this function returns.
24566ae05893dd7b3c86e0c8a79b498fe0cd96deda59Paul Stewart  service = provider->CreateTemporaryService(args, error);
2457d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  if (!service || !error->IsSuccess()) {
2458d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart    // Service::CreateTemporaryService() failed, and has set the error
2459d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart    // appropriately.
2460cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan    return nullptr;
2461d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  }
2462d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart
2463d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // The profile may already have configuration for this service.
2464d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  profile->ConfigureService(service);
2465d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart
2466d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  SetupServiceInProfile(service, profile, args, error);
2467d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart
2468d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // Although we have succeeded, this service will not exist, so its
2469d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  // path is of no use to the caller.
2470d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  DCHECK(service->HasOneRef());
2471cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan  return nullptr;
2472d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart}
2473d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart
2474d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewartvoid Manager::SetupServiceInProfile(ServiceRefPtr service,
2475d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart                                    ProfileRefPtr profile,
24768ae18741780300de3126826b72593391f2d00313Paul Stewart                                    const KeyValueStore& args,
24778ae18741780300de3126826b72593391f2d00313Paul Stewart                                    Error* error) {
2478d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  service->SetProfile(profile);
2479d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  service->Configure(args, error);
2480d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart  profile->UpdateService(service);
2481d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart}
2482d2e1c360880fe0f23ee7dac785ca1c247544aac1Paul Stewart
24838ae18741780300de3126826b72593391f2d00313Paul StewartServiceRefPtr Manager::FindMatchingService(const KeyValueStore& args,
24848ae18741780300de3126826b72593391f2d00313Paul Stewart                                           Error* error) {
24858ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_) {
24866db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (service->DoPropertiesMatch(args)) {
24876db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart      return service;
24887a20aa492230e9e969c8853ad684be0c5b224479Paul Stewart    }
24897a20aa492230e9e969c8853ad684be0c5b224479Paul Stewart  }
24907a20aa492230e9e969c8853ad684be0c5b224479Paul Stewart  error->Populate(Error::kNotFound, "Matching service was not found");
2491cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan  return nullptr;
24927a20aa492230e9e969c8853ad684be0c5b224479Paul Stewart}
24937a20aa492230e9e969c8853ad684be0c5b224479Paul Stewart
24947de7e02e14074989757a4f9f220de2310cc05236Paul Stewartconst map<string, GeolocationInfos>
24957de7e02e14074989757a4f9f220de2310cc05236Paul Stewart    &Manager::GetNetworksForGeolocation() const {
24967de7e02e14074989757a4f9f220de2310cc05236Paul Stewart  return networks_for_geolocation_;
24977de7e02e14074989757a4f9f220de2310cc05236Paul Stewart}
24987de7e02e14074989757a4f9f220de2310cc05236Paul Stewart
24998ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::OnDeviceGeolocationInfoUpdated(const DeviceRefPtr& device) {
2500c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << __func__ << " for technology "
2501c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein                << Technology::NameFromIdentifier(device->technology());
25027de7e02e14074989757a4f9f220de2310cc05236Paul Stewart  switch (device->technology()) {
25037de7e02e14074989757a4f9f220de2310cc05236Paul Stewart    // TODO(gauravsh): crbug.com/217833 Need a strategy for combining
25047de7e02e14074989757a4f9f220de2310cc05236Paul Stewart    // geolocation objects from multiple devices of the same technolgy.
25057de7e02e14074989757a4f9f220de2310cc05236Paul Stewart    // Currently, we just override the any previously acquired
25067de7e02e14074989757a4f9f220de2310cc05236Paul Stewart    // geolocation objects for the retrieved technology type.
25077de7e02e14074989757a4f9f220de2310cc05236Paul Stewart    case Technology::kWifi:
25087de7e02e14074989757a4f9f220de2310cc05236Paul Stewart      networks_for_geolocation_[kGeoWifiAccessPointsProperty] =
25097de7e02e14074989757a4f9f220de2310cc05236Paul Stewart          device->GetGeolocationObjects();
25107de7e02e14074989757a4f9f220de2310cc05236Paul Stewart      break;
25117de7e02e14074989757a4f9f220de2310cc05236Paul Stewart    case Technology::kCellular:
25127de7e02e14074989757a4f9f220de2310cc05236Paul Stewart      networks_for_geolocation_[kGeoCellTowersProperty] =
25137de7e02e14074989757a4f9f220de2310cc05236Paul Stewart          device->GetGeolocationObjects();
25147de7e02e14074989757a4f9f220de2310cc05236Paul Stewart      break;
25157de7e02e14074989757a4f9f220de2310cc05236Paul Stewart    default:
25167de7e02e14074989757a4f9f220de2310cc05236Paul Stewart      // Ignore other technologies.
25177de7e02e14074989757a4f9f220de2310cc05236Paul Stewart      break;
2518b790aa2e5b6422cbba4a20be81ba1c0445701405Gaurav Shah  }
25197de7e02e14074989757a4f9f220de2310cc05236Paul Stewart}
2520b790aa2e5b6422cbba4a20be81ba1c0445701405Gaurav Shah
25218ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::RecheckPortal(Error* /*error*/) {
25228ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
25236db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (device->RequestPortalDetection()) {
2524c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart      // Only start Portal Detection on the device with the default connection.
2525c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart      // We will get a "true" return value when we've found that device, and
2526c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart      // can end our loop early as a result.
2527c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart      break;
2528c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart    }
2529c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart  }
2530c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart}
2531c681fa0742cabc686ccabaf0fdf6ce12dd7046b2Paul Stewart
25328ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::RecheckPortalOnService(const ServiceRefPtr& service) {
25338ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
25346db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (device->IsConnectedToService(service)) {
2535d215af6f72d012f43057c34f17a12506baa21e66Paul Stewart      // As opposed to RecheckPortal() above, we explicitly stop and then
2536d215af6f72d012f43057c34f17a12506baa21e66Paul Stewart      // restart portal detection, since the service to recheck was explicitly
2537d215af6f72d012f43057c34f17a12506baa21e66Paul Stewart      // specified.
25386db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart      device->RestartPortalDetection();
2539d215af6f72d012f43057c34f17a12506baa21e66Paul Stewart      break;
2540d215af6f72d012f43057c34f17a12506baa21e66Paul Stewart    }
2541d215af6f72d012f43057c34f17a12506baa21e66Paul Stewart  }
2542d215af6f72d012f43057c34f17a12506baa21e66Paul Stewart}
2543d215af6f72d012f43057c34f17a12506baa21e66Paul Stewart
254468d4109ff0176f7e5a9b67b916478d638aac577aWade Guthrievoid Manager::RequestScan(Device::ScanType scan_type,
25458ae18741780300de3126826b72593391f2d00313Paul Stewart                          const string& technology, Error* error) {
2546923a5025a5e1138b052cbeffa60ea387d479696fBen Chan  if (technology == kTypeWifi || technology == "") {
25478ae18741780300de3126826b72593391f2d00313Paul Stewart    for (const auto& wifi_device : FilterByTechnology(Technology::kWifi)) {
2548e783f1c2004e35db6eff036e5d7b3a5b99b724ffPeter Qiu      metrics_->NotifyUserInitiatedEvent(Metrics::kUserInitiatedEventWifiScan);
25496db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart      wifi_device->Scan(scan_type, error, __func__);
25503239932e4a0a92fec52d88860081cbbb003eabb0mukesh agrawal    }
25513239932e4a0a92fec52d88860081cbbb003eabb0mukesh agrawal  } else {
25523239932e4a0a92fec52d88860081cbbb003eabb0mukesh agrawal    // TODO(quiche): support scanning for other technologies?
255334f424e672439bdf237a755f85245ebd7b66e8e2Paul Stewart    Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
2554be005174bce39ddad185c2eb6808117484d522adPaul Stewart                          "Unrecognized technology " + technology);
25553239932e4a0a92fec52d88860081cbbb003eabb0mukesh agrawal  }
25563239932e4a0a92fec52d88860081cbbb003eabb0mukesh agrawal}
25573239932e4a0a92fec52d88860081cbbb003eabb0mukesh agrawal
25588ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::SetSchedScan(bool enable, Error* error) {
25598ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& wifi_device : FilterByTechnology(Technology::kWifi)) {
2560d51b24406ed78691abe1c8110029a197c351a6e9Peter Qiu    wifi_device->SetSchedScan(enable, error);
2561d51b24406ed78691abe1c8110029a197c351a6e9Peter Qiu  }
2562d51b24406ed78691abe1c8110029a197c351a6e9Peter Qiu}
2563d51b24406ed78691abe1c8110029a197c351a6e9Peter Qiu
256422aa71b334c716f20999c2e08e5b797207b0afaePaul Stewartstring Manager::GetTechnologyOrder() {
256522aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart  vector<string> technology_names;
25668ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& technology : technology_order_) {
25676db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    technology_names.push_back(Technology::NameFromIdentifier(technology));
256822aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart  }
256922aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart
25703a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko  return base::JoinString(technology_names, ",");
257122aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart}
257222aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart
25738ae18741780300de3126826b72593391f2d00313Paul Stewartvoid Manager::SetTechnologyOrder(const string& order, Error* error) {
257422aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart  vector<Technology::Identifier> new_order;
2575c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein  SLOG(this, 2) << "Setting technology order to " << order;
257620088d860631a67c151a12783fbbee63c708792fPaul Stewart  if (!Technology::GetTechnologyVectorFromString(order, &new_order, error)) {
257720088d860631a67c151a12783fbbee63c708792fPaul Stewart    return;
257822aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart  }
257922aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart
258022aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart  technology_order_ = new_order;
25811ce231c71932200e4d02c71567f8e93788120781Paul Stewart  if (running_) {
25821ce231c71932200e4d02c71567f8e93788120781Paul Stewart    SortServices();
25831ce231c71932200e4d02c71567f8e93788120781Paul Stewart  }
258422aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart}
258522aa71b334c716f20999c2e08e5b797207b0afaePaul Stewart
2586574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiubool Manager::IsWifiIdle() {
2587574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu  bool ret = false;
2588574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu
2589574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu  // Since services are sorted by connection state, status of the wifi device
2590574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu  // can be determine by examing the connection state of the first wifi service.
25918ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& service : services_) {
2592574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu    if (service->technology() == Technology::kWifi) {
2593574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu      if (!service->IsConnecting() && !service->IsConnected()) {
2594574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu        ret = true;
2595574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu      }
2596574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu      break;
2597574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu    }
2598574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu  }
2599574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu  return ret;
2600574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu}
2601574996af8ed3e3c2fe2bc16970f73c665296cfccPeter Qiu
2602b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewartvoid Manager::UpdateProviderMapping() {
26031a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIRED_8021X)
2604b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart  providers_[Technology::kEthernetEap] = ethernet_eap_provider_.get();
26051a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif  // DISABLE_WIRED_8021X
2606b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart  providers_[Technology::kVPN] = vpn_provider_.get();
26071a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#if !defined(DISABLE_WIFI)
2608b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart  providers_[Technology::kWifi] = wifi_provider_.get();
26091a72f5444e077ed21b8e085b17d7f9f1bc44fa5ePeter Qiu#endif  // DISABLE_WIFI
2610520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan#if !defined(DISABLE_WIMAX)
2611b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart  providers_[Technology::kWiMax] = wimax_provider_.get();
2612520eb176ecc8548a9eb6a340fb46c06618ee8308Ben Chan#endif  // DISABLE_WIMAX
2613b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart}
2614b87d22b774fe15b6580d13638d5f0514bde031fdPaul Stewart
2615fe734676357045eab81ab62fc3ea7ae1a40ed905Samuel TanDeviceRefPtr Manager::GetDeviceConnectedToService(ServiceRefPtr service) {
2616fe734676357045eab81ab62fc3ea7ae1a40ed905Samuel Tan  for (DeviceRefPtr device : devices_) {
2617fe734676357045eab81ab62fc3ea7ae1a40ed905Samuel Tan    if (device->IsConnectedToService(service)) {
2618fe734676357045eab81ab62fc3ea7ae1a40ed905Samuel Tan      return device;
2619fe734676357045eab81ab62fc3ea7ae1a40ed905Samuel Tan    }
2620fe734676357045eab81ab62fc3ea7ae1a40ed905Samuel Tan  }
2621fe734676357045eab81ab62fc3ea7ae1a40ed905Samuel Tan  return nullptr;
2622fe734676357045eab81ab62fc3ea7ae1a40ed905Samuel Tan}
2623fe734676357045eab81ab62fc3ea7ae1a40ed905Samuel Tan
26242cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewartvoid Manager::DetectMultiHomedDevices() {
26252cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart  map<string, vector<DeviceRefPtr>> subnet_buckets;
26268ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& device : devices_) {
26278ae18741780300de3126826b72593391f2d00313Paul Stewart    const auto& connection = device->connection();
2628182888eab7478f28001b1235f8d2b75063445db8Paul Stewart    string subnet_name;
2629182888eab7478f28001b1235f8d2b75063445db8Paul Stewart    if (connection) {
2630182888eab7478f28001b1235f8d2b75063445db8Paul Stewart      subnet_name = connection->GetSubnetName();
2631182888eab7478f28001b1235f8d2b75063445db8Paul Stewart    }
2632182888eab7478f28001b1235f8d2b75063445db8Paul Stewart    if (subnet_name.empty()) {
26332cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart      device->SetIsMultiHomed(false);
26342cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart    } else {
2635182888eab7478f28001b1235f8d2b75063445db8Paul Stewart      subnet_buckets[subnet_name].push_back(device);
26362cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart    }
26372cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart  }
26382cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart
26398ae18741780300de3126826b72593391f2d00313Paul Stewart  for (const auto& subnet_bucket : subnet_buckets) {
26408ae18741780300de3126826b72593391f2d00313Paul Stewart    const auto& device_list = subnet_bucket.second;
26412cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart    if (device_list.size() > 1) {
26428ae18741780300de3126826b72593391f2d00313Paul Stewart      for (const auto& device : device_list) {
26432cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart        device->SetIsMultiHomed(true);
26442cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart      }
26452cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart    } else {
26462cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart      DCHECK_EQ(1U, device_list.size());
26472cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart      device_list.back()->SetIsMultiHomed(false);
26482cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart    }
26492cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart  }
26502cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart}
26512cb3fa7317cfa3248cff72d0b9d64c4f2f630472Paul Stewart
265275897df1154ac38b7a4512a687241ad6a197ee40Paul Stewart}  // namespace shill
2653