Home | History | Annotate | Download | only in shill
      1 //
      2 // Copyright (C) 2012 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "shill/manager.h"
     18 
     19 #include <stdio.h>
     20 #include <time.h>
     21 
     22 #include <algorithm>
     23 #include <set>
     24 #include <string>
     25 #include <vector>
     26 
     27 #include <base/bind.h>
     28 #include <base/callback.h>
     29 #include <base/files/file_util.h>
     30 #include <base/memory/ref_counted.h>
     31 #include <base/strings/pattern.h>
     32 #include <base/strings/stringprintf.h>
     33 #include <base/strings/string_split.h>
     34 #include <base/strings/string_util.h>
     35 #if defined(__ANDROID__)
     36 #include <dbus/service_constants.h>
     37 #else
     38 #include <chromeos/dbus/service_constants.h>
     39 #endif  // __ANDROID__
     40 
     41 #include "shill/adaptor_interfaces.h"
     42 #include "shill/callbacks.h"
     43 #include "shill/connection.h"
     44 #include "shill/control_interface.h"
     45 #include "shill/default_profile.h"
     46 #include "shill/device.h"
     47 #include "shill/device_claimer.h"
     48 #include "shill/device_info.h"
     49 #include "shill/ephemeral_profile.h"
     50 #include "shill/error.h"
     51 #include "shill/ethernet/ethernet_temporary_service.h"
     52 #include "shill/event_dispatcher.h"
     53 #include "shill/geolocation_info.h"
     54 #include "shill/hook_table.h"
     55 #include "shill/ip_address_store.h"
     56 #include "shill/logging.h"
     57 #include "shill/profile.h"
     58 #include "shill/property_accessor.h"
     59 #include "shill/resolver.h"
     60 #include "shill/result_aggregator.h"
     61 #include "shill/service.h"
     62 #include "shill/service_sorter.h"
     63 #include "shill/store_factory.h"
     64 #include "shill/vpn/vpn_provider.h"
     65 #include "shill/vpn/vpn_service.h"
     66 #include "shill/wimax/wimax_service.h"
     67 
     68 #if defined(__BRILLO__)
     69 #include "shill/wifi/wifi_driver_hal.h"
     70 #endif  // __BRILLO__
     71 
     72 #if !defined(DISABLE_WIFI)
     73 #include "shill/wifi/wifi.h"
     74 #include "shill/wifi/wifi_provider.h"
     75 #include "shill/wifi/wifi_service.h"
     76 #endif  // DISABLE_WIFI
     77 
     78 #if !defined(DISABLE_WIRED_8021X)
     79 #include "shill/ethernet/ethernet_eap_provider.h"
     80 #include "shill/ethernet/ethernet_eap_service.h"
     81 #endif  // DISABLE_WIRED_8021X
     82 
     83 using base::Bind;
     84 using base::Callback;
     85 using base::FilePath;
     86 using base::StringPrintf;
     87 using base::Unretained;
     88 using std::map;
     89 using std::set;
     90 using std::string;
     91 using std::vector;
     92 
     93 namespace shill {
     94 
     95 namespace Logging {
     96 static auto kModuleLogScope = ScopeLogger::kManager;
     97 static string ObjectID(const Manager* m) { return "manager"; }
     98 }
     99 
    100 
    101 // statics
    102 const char Manager::kErrorNoDevice[] = "no wifi devices available";
    103 const char Manager::kErrorTypeRequired[] = "must specify service type";
    104 const char Manager::kErrorUnsupportedServiceType[] =
    105     "service type is unsupported";
    106 // This timeout should be less than the upstart job timeout, otherwise
    107 // stats for termination actions might be lost.
    108 const int Manager::kTerminationActionsTimeoutMilliseconds = 19500;
    109 
    110 // Device status check interval (every 3 minutes).
    111 const int Manager::kDeviceStatusCheckIntervalMilliseconds = 180000;
    112 
    113 // static
    114 const char* Manager::kProbeTechnologies[] = {
    115     kTypeEthernet,
    116     kTypeWifi,
    117     kTypeWimax,
    118     kTypeCellular
    119 };
    120 
    121 // static
    122 const char Manager::kDefaultClaimerName[] = "";
    123 
    124 Manager::Manager(ControlInterface* control_interface,
    125                  EventDispatcher* dispatcher,
    126                  Metrics* metrics,
    127                  const string& run_directory,
    128                  const string& storage_directory,
    129                  const string& user_storage_directory)
    130     : dispatcher_(dispatcher),
    131       run_path_(FilePath(run_directory)),
    132       storage_path_(FilePath(storage_directory)),
    133       user_storage_path_(user_storage_directory),
    134       user_profile_list_path_(FilePath(Profile::kUserProfileListPathname)),
    135       adaptor_(control_interface->CreateManagerAdaptor(this)),
    136       device_info_(control_interface, dispatcher, metrics, this),
    137 #if !defined(DISABLE_CELLULAR)
    138       modem_info_(control_interface, dispatcher, metrics, this),
    139 #endif  // DISABLE_CELLULAR
    140 #if !defined(DISABLE_WIRED_8021X)
    141       ethernet_eap_provider_(
    142           new EthernetEapProvider(
    143               control_interface, dispatcher, metrics, this)),
    144 #endif  // DISABLE_WIRED_8021X
    145       vpn_provider_(
    146           new VPNProvider(control_interface, dispatcher, metrics, this)),
    147 #if !defined(DISABLE_WIFI)
    148       wifi_provider_(
    149           new WiFiProvider(control_interface, dispatcher, metrics, this)),
    150 #if defined(__BRILLO__)
    151       wifi_driver_hal_(WiFiDriverHal::GetInstance()),
    152 #endif  // __BRILLO__
    153 #endif  // DISABLE_WIFI
    154 #if !defined(DISABLE_WIMAX)
    155       wimax_provider_(
    156           new WiMaxProvider(control_interface, dispatcher, metrics, this)),
    157 #endif  // DISABLE_WIMAX
    158       resolver_(Resolver::GetInstance()),
    159       running_(false),
    160       connect_profiles_to_rpc_(true),
    161       ephemeral_profile_(
    162           new EphemeralProfile(control_interface, metrics, this)),
    163       control_interface_(control_interface),
    164       metrics_(metrics),
    165       use_startup_portal_list_(false),
    166       device_status_check_task_(Bind(&Manager::DeviceStatusCheckTask,
    167                                      base::Unretained(this))),
    168       termination_actions_(dispatcher),
    169       suspend_delay_registered_(false),
    170       is_wake_on_lan_enabled_(true),
    171       ignore_unknown_ethernet_(false),
    172       default_service_callback_tag_(0),
    173       crypto_util_proxy_(new CryptoUtilProxy(dispatcher)),
    174       health_checker_remote_ips_(new IPAddressStore()),
    175       suppress_autoconnect_(false),
    176       is_connected_state_(false),
    177       dhcp_properties_(new DhcpProperties()) {
    178   HelpRegisterDerivedString(kActiveProfileProperty,
    179                             &Manager::GetActiveProfileRpcIdentifier,
    180                             nullptr);
    181   store_.RegisterBool(kArpGatewayProperty, &props_.arp_gateway);
    182   HelpRegisterConstDerivedStrings(kAvailableTechnologiesProperty,
    183                                   &Manager::AvailableTechnologies);
    184   HelpRegisterDerivedString(kCheckPortalListProperty,
    185                             &Manager::GetCheckPortalList,
    186                             &Manager::SetCheckPortalList);
    187   HelpRegisterConstDerivedStrings(kConnectedTechnologiesProperty,
    188                                   &Manager::ConnectedTechnologies);
    189   store_.RegisterConstString(kConnectionStateProperty, &connection_state_);
    190   store_.RegisterString(kCountryProperty, &props_.country);
    191   HelpRegisterDerivedString(kDefaultTechnologyProperty,
    192                             &Manager::DefaultTechnology,
    193                             nullptr);
    194   HelpRegisterConstDerivedRpcIdentifier(
    195       kDefaultServiceProperty, &Manager::GetDefaultServiceRpcIdentifier);
    196   HelpRegisterConstDerivedRpcIdentifiers(kDevicesProperty,
    197                                          &Manager::EnumerateDevices);
    198 #if !defined(DISABLE_WIFI)
    199   HelpRegisterDerivedBool(kDisableWiFiVHTProperty,
    200                           &Manager::GetDisableWiFiVHT,
    201                           &Manager::SetDisableWiFiVHT);
    202 #endif  // DISABLE_WIFI
    203   HelpRegisterConstDerivedStrings(kEnabledTechnologiesProperty,
    204                                   &Manager::EnabledTechnologies);
    205   HelpRegisterDerivedString(kIgnoredDNSSearchPathsProperty,
    206                             &Manager::GetIgnoredDNSSearchPaths,
    207                             &Manager::SetIgnoredDNSSearchPaths);
    208   store_.RegisterString(kHostNameProperty, &props_.host_name);
    209   store_.RegisterString(kLinkMonitorTechnologiesProperty,
    210                         &props_.link_monitor_technologies);
    211   store_.RegisterString(kNoAutoConnectTechnologiesProperty,
    212                         &props_.no_auto_connect_technologies);
    213   store_.RegisterBool(kOfflineModeProperty, &props_.offline_mode);
    214   store_.RegisterString(kPortalURLProperty, &props_.portal_url);
    215   store_.RegisterInt32(kPortalCheckIntervalProperty,
    216                        &props_.portal_check_interval_seconds);
    217   HelpRegisterConstDerivedRpcIdentifiers(kProfilesProperty,
    218                                          &Manager::EnumerateProfiles);
    219   HelpRegisterDerivedString(kProhibitedTechnologiesProperty,
    220                             &Manager::GetProhibitedTechnologies,
    221                             &Manager::SetProhibitedTechnologies);
    222   HelpRegisterDerivedString(kStateProperty,
    223                             &Manager::CalculateState,
    224                             nullptr);
    225   HelpRegisterConstDerivedRpcIdentifiers(kServicesProperty,
    226                                          &Manager::EnumerateAvailableServices);
    227   HelpRegisterConstDerivedRpcIdentifiers(kServiceCompleteListProperty,
    228                                          &Manager::EnumerateCompleteServices);
    229   HelpRegisterConstDerivedRpcIdentifiers(kServiceWatchListProperty,
    230                                          &Manager::EnumerateWatchedServices);
    231   HelpRegisterConstDerivedStrings(kUninitializedTechnologiesProperty,
    232                                   &Manager::UninitializedTechnologies);
    233   store_.RegisterBool(kWakeOnLanEnabledProperty, &is_wake_on_lan_enabled_);
    234   HelpRegisterConstDerivedStrings(kClaimedDevicesProperty,
    235                                   &Manager::ClaimedDevices);
    236 
    237   UpdateProviderMapping();
    238 
    239   dhcp_properties_->InitPropertyStore(&store_);
    240 
    241   SLOG(this, 2) << "Manager initialized.";
    242 }
    243 
    244 Manager::~Manager() {}
    245 
    246 void Manager::RegisterAsync(const Callback<void(bool)>& completion_callback) {
    247   adaptor_->RegisterAsync(completion_callback);
    248 }
    249 
    250 void Manager::SetBlacklistedDevices(const vector<string>& blacklisted_devices) {
    251   blacklisted_devices_ = blacklisted_devices;
    252 }
    253 
    254 void Manager::SetWhitelistedDevices(const vector<string>& whitelisted_devices) {
    255   whitelisted_devices_ = whitelisted_devices;
    256 }
    257 
    258 void Manager::Start() {
    259   LOG(INFO) << "Manager started.";
    260 
    261   power_manager_.reset(
    262       new PowerManager(dispatcher_, control_interface_));
    263   power_manager_->Start(base::TimeDelta::FromMilliseconds(
    264                             kTerminationActionsTimeoutMilliseconds),
    265                         Bind(&Manager::OnSuspendImminent, AsWeakPtr()),
    266                         Bind(&Manager::OnSuspendDone, AsWeakPtr()),
    267                         Bind(&Manager::OnDarkSuspendImminent, AsWeakPtr()));
    268   upstart_.reset(new Upstart(control_interface_));
    269 
    270   CHECK(base::CreateDirectory(run_path_)) << run_path_.value();
    271   resolver_->set_path(run_path_.Append("resolv.conf"));
    272 
    273   InitializeProfiles();
    274   running_ = true;
    275   device_info_.Start();
    276 #if !defined(DISABLE_CELLULAR)
    277   modem_info_.Start();
    278 #endif  // DISABLE_CELLULAR
    279   for (const auto& provider_mapping : providers_) {
    280     provider_mapping.second->Start();
    281   }
    282 
    283   // Start task for checking connection status.
    284   dispatcher_->PostDelayedTask(device_status_check_task_.callback(),
    285                                kDeviceStatusCheckIntervalMilliseconds);
    286 }
    287 
    288 void Manager::Stop() {
    289   running_ = false;
    290   // Persist device information to disk;
    291   for (const auto& device : devices_) {
    292     UpdateDevice(device);
    293   }
    294 
    295 #if !defined(DISABLE_WIFI)
    296   UpdateWiFiProvider();
    297 #endif  // DISABLE_WIFI
    298 
    299   // Persist profile, service information to disk.
    300   for (const auto& profile : profiles_) {
    301     // Since this happens in a loop, the current manager state is stored to
    302     // all default profiles in the stack.  This is acceptable because the
    303     // only time multiple default profiles are loaded are during autotests.
    304     profile->Save();
    305   }
    306 
    307   Error e;
    308   for (const auto& service : services_) {
    309     service->Disconnect(&e, __func__);
    310   }
    311 
    312   for (const auto& device : devices_) {
    313     device->SetEnabled(false);
    314   }
    315 
    316   for (const auto& provider_mapping : providers_) {
    317     provider_mapping.second->Stop();
    318   }
    319 #if !defined(DISABLE_CELLULAR)
    320   modem_info_.Stop();
    321 #endif  // DISABLE_CELLULAR
    322   device_info_.Stop();
    323   device_status_check_task_.Cancel();
    324   sort_services_task_.Cancel();
    325   power_manager_->Stop();
    326   power_manager_.reset();
    327 }
    328 
    329 void Manager::InitializeProfiles() {
    330   DCHECK(profiles_.empty());  // The default profile must go first on stack.
    331   CHECK(base::CreateDirectory(storage_path_)) << storage_path_.value();
    332 
    333   // Ensure that we have storage for the default profile, and that
    334   // the persistent copy of the default profile is not corrupt.
    335   scoped_refptr<DefaultProfile>
    336       default_profile(new DefaultProfile(control_interface_,
    337                                          metrics_,
    338                                          this,
    339                                          storage_path_,
    340                                          DefaultProfile::kDefaultId,
    341                                          props_));
    342   // The default profile may fail to initialize if it's corrupted.
    343   // If so, recreate the default profile.
    344   if (!default_profile->InitStorage(Profile::kCreateOrOpenExisting, nullptr))
    345     CHECK(default_profile->InitStorage(Profile::kCreateNew, nullptr));
    346   // In case we created a new profile, initialize its default values,
    347   // and then save. This is required for properties such as
    348   // PortalDetector::kDefaultCheckPortalList to be initialized correctly.
    349   LoadProperties(default_profile);
    350   default_profile->Save();
    351   default_profile = nullptr;  // PushProfileInternal will re-create.
    352 
    353   // Read list of user profiles. This must be done before pushing the
    354   // default profile, because modifying the profile stack updates the
    355   // user profile list.
    356   vector<Profile::Identifier> identifiers =
    357       Profile::LoadUserProfileList(user_profile_list_path_);
    358 
    359   // Push the default profile onto the stack.
    360   Error error;
    361   string path;
    362   Profile::Identifier default_profile_id;
    363   CHECK(Profile::ParseIdentifier(
    364       DefaultProfile::kDefaultId, &default_profile_id));
    365   PushProfileInternal(default_profile_id, &path, &error);
    366   CHECK(!profiles_.empty());  // Must have a default profile.
    367 
    368   // Push user profiles onto the stack.
    369   for (const auto& profile_id : identifiers)  {
    370     PushProfileInternal(profile_id, &path, &error);
    371   }
    372 }
    373 
    374 void Manager::CreateProfile(const string& name, string* path, Error* error) {
    375   SLOG(this, 2) << __func__ << " " << name;
    376   Profile::Identifier ident;
    377   if (!Profile::ParseIdentifier(name, &ident)) {
    378     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
    379                           "Invalid profile name " + name);
    380     return;
    381   }
    382 
    383   if (HasProfile(ident)) {
    384     Error::PopulateAndLog(FROM_HERE, error, Error::kAlreadyExists,
    385                           "Profile name " + name + " is already on stack");
    386     return;
    387   }
    388 
    389   ProfileRefPtr profile;
    390   if (ident.user.empty()) {
    391     profile = new DefaultProfile(control_interface_,
    392                                  metrics_,
    393                                  this,
    394                                  storage_path_,
    395                                  ident.identifier,
    396                                  props_);
    397   } else {
    398     profile = new Profile(control_interface_,
    399                           metrics_,
    400                           this,
    401                           ident,
    402                           user_storage_path_,
    403                           true);
    404   }
    405 
    406   if (!profile->InitStorage(Profile::kCreateNew, error)) {
    407     // |error| will have been populated by InitStorage().
    408     return;
    409   }
    410 
    411   // Save profile data out, and then let the scoped pointer fall out of scope.
    412   if (!profile->Save()) {
    413     Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError,
    414                           "Profile name " + name + " could not be saved");
    415     return;
    416   }
    417 
    418   *path = profile->GetRpcIdentifier();
    419 }
    420 
    421 bool Manager::HasProfile(const Profile::Identifier& ident) {
    422   for (const auto& profile : profiles_) {
    423     if (profile->MatchesIdentifier(ident)) {
    424       return true;
    425     }
    426   }
    427   return false;
    428 }
    429 
    430 void Manager::PushProfileInternal(
    431     const Profile::Identifier& ident, string* path, Error* error) {
    432   if (HasProfile(ident)) {
    433     Error::PopulateAndLog(FROM_HERE, error, Error::kAlreadyExists,
    434                           "Profile name " + Profile::IdentifierToString(ident) +
    435                           " is already on stack");
    436     return;
    437   }
    438 
    439   ProfileRefPtr profile;
    440   if (ident.user.empty()) {
    441     // Allow a machine-wide-profile to be pushed on the stack only if the
    442     // profile stack is empty, or if the topmost profile on the stack is
    443     // also a machine-wide (non-user) profile.
    444     if (!profiles_.empty() && !profiles_.back()->GetUser().empty()) {
    445       Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
    446                             "Cannot load non-default global profile " +
    447                             Profile::IdentifierToString(ident) +
    448                             " on top of a user profile");
    449       return;
    450     }
    451 
    452     scoped_refptr<DefaultProfile>
    453         default_profile(new DefaultProfile(control_interface_,
    454                                            metrics_,
    455                                            this,
    456                                            storage_path_,
    457                                            ident.identifier,
    458                                            props_));
    459     if (!default_profile->InitStorage(Profile::kOpenExisting, nullptr)) {
    460       LOG(ERROR) << "Failed to open default profile.";
    461       // Try to continue anyway, so that we can be useful in cases
    462       // where the disk is full.
    463       default_profile->InitStubStorage();
    464     }
    465 
    466     LoadProperties(default_profile);
    467     profile = default_profile;
    468   } else {
    469     profile = new Profile(control_interface_,
    470                           metrics_,
    471                           this,
    472                           ident,
    473                           user_storage_path_,
    474                           connect_profiles_to_rpc_);
    475     if (!profile->InitStorage(Profile::kOpenExisting, error)) {
    476       // |error| will have been populated by InitStorage().
    477       return;
    478     }
    479   }
    480 
    481   profiles_.push_back(profile);
    482 
    483   for (ServiceRefPtr& service : services_) {
    484     service->ClearExplicitlyDisconnected();
    485 
    486     // Offer each registered Service the opportunity to join this new Profile.
    487     if (profile->ConfigureService(service)) {
    488       LOG(INFO) << "(Re-)configured service " << service->unique_name()
    489                 << " from new profile.";
    490     }
    491   }
    492 
    493   // Shop the Profile contents around to Devices which may have configuration
    494   // stored in these profiles.
    495   for (DeviceRefPtr& device : devices_) {
    496     profile->ConfigureDevice(device);
    497   }
    498 
    499   // Offer the Profile contents to the service providers which will
    500   // create new services if necessary.
    501   for (const auto& provider_mapping : providers_) {
    502     provider_mapping.second->CreateServicesFromProfile(profile);
    503   }
    504 
    505   *path = profile->GetRpcIdentifier();
    506   SortServices();
    507   OnProfilesChanged();
    508   LOG(INFO) << __func__ << " finished; " << profiles_.size()
    509             << " profile(s) now present.";
    510 }
    511 
    512 void Manager::PushProfile(const string& name, string* path, Error* error) {
    513   SLOG(this, 2) << __func__ << " " << name;
    514   Profile::Identifier ident;
    515   if (!Profile::ParseIdentifier(name, &ident)) {
    516     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
    517                           "Invalid profile name " + name);
    518     return;
    519   }
    520   PushProfileInternal(ident, path, error);
    521 }
    522 
    523 void Manager::InsertUserProfile(const string& name,
    524                                 const string& user_hash,
    525                                 string* path,
    526                                 Error* error) {
    527   SLOG(this, 2) << __func__ << " " << name;
    528   Profile::Identifier ident;
    529   if (!Profile::ParseIdentifier(name, &ident) ||
    530       ident.user.empty()) {
    531     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
    532                           "Invalid user profile name " + name);
    533     return;
    534   }
    535   ident.user_hash = user_hash;
    536   PushProfileInternal(ident, path, error);
    537 }
    538 
    539 void Manager::PopProfileInternal() {
    540   CHECK(!profiles_.empty());
    541   ProfileRefPtr active_profile = profiles_.back();
    542   profiles_.pop_back();
    543   for (auto it = services_.begin(); it != services_.end();) {
    544     (*it)->ClearExplicitlyDisconnected();
    545     if (IsServiceEphemeral(*it)) {
    546       // Not affected, since the EphemeralProfile isn't on the stack.
    547       // Not logged, since ephemeral services aren't that interesting.
    548       ++it;
    549       continue;
    550     }
    551 
    552     if ((*it)->profile().get() != active_profile.get()) {
    553       LOG(INFO) << "Skipping unload of service " << (*it)->unique_name()
    554                 << ": wasn't using this profile.";
    555       ++it;
    556       continue;
    557     }
    558 
    559     if (MatchProfileWithService(*it)) {
    560       LOG(INFO) << "Skipping unload of service " << (*it)->unique_name()
    561                 << ": re-configured from another profile.";
    562       ++it;
    563       continue;
    564     }
    565 
    566     if (!UnloadService(&it)) {
    567       LOG(INFO) << "Service " << (*it)->unique_name()
    568                 << " not completely unloaded.";
    569       ++it;
    570       continue;
    571     }
    572 
    573     // Service was totally unloaded. No advance of iterator in this
    574     // case, as UnloadService has updated the iterator for us.
    575   }
    576   SortServices();
    577   OnProfilesChanged();
    578   LOG(INFO) << __func__ << " finished; " << profiles_.size()
    579             << " profile(s) still present.";
    580 }
    581 
    582 void Manager::OnProfilesChanged() {
    583   Error unused_error;
    584 
    585   adaptor_->EmitStringsChanged(kProfilesProperty,
    586                                EnumerateProfiles(&unused_error));
    587   Profile::SaveUserProfileList(user_profile_list_path_, profiles_);
    588 }
    589 
    590 void Manager::PopProfile(const string& name, Error* error) {
    591   SLOG(this, 2) << __func__ << " " << name;
    592   Profile::Identifier ident;
    593   if (profiles_.empty()) {
    594     Error::PopulateAndLog(
    595         FROM_HERE, error, Error::kNotFound, "Profile stack is empty");
    596     return;
    597   }
    598   ProfileRefPtr active_profile = profiles_.back();
    599   if (!Profile::ParseIdentifier(name, &ident)) {
    600     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
    601                           "Invalid profile name " + name);
    602     return;
    603   }
    604   if (!active_profile->MatchesIdentifier(ident)) {
    605     Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
    606                           name + " is not the active profile");
    607     return;
    608   }
    609   PopProfileInternal();
    610 }
    611 
    612 void Manager::PopAnyProfile(Error* error) {
    613   SLOG(this, 2) << __func__;
    614   Profile::Identifier ident;
    615   if (profiles_.empty()) {
    616     Error::PopulateAndLog(
    617         FROM_HERE, error, Error::kNotFound, "Profile stack is empty");
    618     return;
    619   }
    620   PopProfileInternal();
    621 }
    622 
    623 void Manager::PopAllUserProfiles(Error* /*error*/) {
    624   SLOG(this, 2) << __func__;
    625   while (!profiles_.empty() && !profiles_.back()->GetUser().empty()) {
    626     PopProfileInternal();
    627   }
    628 }
    629 
    630 void Manager::RemoveProfile(const string& name, Error* error) {
    631   Profile::Identifier ident;
    632   if (!Profile::ParseIdentifier(name, &ident)) {
    633     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
    634                           "Invalid profile name " + name);
    635     return;
    636   }
    637 
    638   if (HasProfile(ident)) {
    639     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
    640                           "Cannot remove profile name " + name +
    641                           " since it is on stack");
    642     return;
    643   }
    644 
    645   ProfileRefPtr profile;
    646   if (ident.user.empty()) {
    647     profile = new DefaultProfile(control_interface_,
    648                                  metrics_,
    649                                  this,
    650                                  storage_path_,
    651                                  ident.identifier,
    652                                  props_);
    653   } else {
    654     profile = new Profile(control_interface_,
    655                           metrics_,
    656                           this,
    657                           ident,
    658                           user_storage_path_,
    659                           false);
    660   }
    661 
    662 
    663   // |error| will have been populated if RemoveStorage fails.
    664   profile->RemoveStorage(error);
    665 
    666   return;
    667 }
    668 
    669 bool Manager::DeviceManagementAllowed(const string& device_name) {
    670   if (std::find(blacklisted_devices_.begin(),
    671                 blacklisted_devices_.end(),
    672                 device_name) != blacklisted_devices_.end()) {
    673     return false;
    674   }
    675   if (!whitelisted_devices_.size()) {
    676     // If no whitelist is specified, all devices are considered whitelisted.
    677     return true;
    678   }
    679   if (std::find(whitelisted_devices_.begin(),
    680                 whitelisted_devices_.end(),
    681                 device_name) != whitelisted_devices_.end()) {
    682     return true;
    683   }
    684   return false;
    685 }
    686 
    687 void Manager::ClaimDevice(const string& claimer_name,
    688                           const string& device_name,
    689                           Error* error) {
    690   SLOG(this, 2) << __func__;
    691 
    692   // Basic check for device name.
    693   if (device_name.empty()) {
    694     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
    695                           "Empty device name");
    696     return;
    697   }
    698 
    699   if (!DeviceManagementAllowed(device_name)) {
    700     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
    701                           "Not allowed to claim unmanaged device");
    702     return;
    703   }
    704 
    705   // Verify default claimer.
    706   if (claimer_name.empty() &&
    707       (!device_claimer_ || !device_claimer_->default_claimer())) {
    708     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
    709                           "No default claimer");
    710     return;
    711   }
    712 
    713   // Create a new device claimer if one doesn't exist yet.
    714   if (!device_claimer_) {
    715     // Start a device claimer.  No need to verify the existence of the claimer,
    716     // since we are using message sender as the claimer name.
    717     device_claimer_.reset(
    718         new DeviceClaimer(claimer_name, &device_info_, false));
    719   }
    720 
    721   // Verify claimer's name, since we only allow one claimer to exist at a time.
    722   if (device_claimer_->name() != claimer_name) {
    723     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
    724                           "Invalid claimer name " + claimer_name +
    725                           ". Claimer " + device_claimer_->name() +
    726                           " already exist");
    727     return;
    728   }
    729 
    730   // Error will be populated by the claimer if failed to claim the device.
    731   if (!device_claimer_->Claim(device_name, error)) {
    732     return;
    733   }
    734 
    735   // Deregister the device from manager if it is registered.
    736   DeregisterDeviceByLinkName(device_name);
    737 }
    738 
    739 void Manager::ReleaseDevice(const string& claimer_name,
    740                             const string& device_name,
    741                             bool* claimer_removed,
    742                             Error* error) {
    743   SLOG(this, 2) << __func__;
    744 
    745   *claimer_removed = false;
    746 
    747   if (!DeviceManagementAllowed(device_name)) {
    748     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
    749                           "Not allowed to release unmanaged device");
    750     return;
    751   }
    752 
    753   if (!device_claimer_) {
    754     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
    755                           "Device claimer doesn't exist");
    756     return;
    757   }
    758 
    759   // Verify claimer's name, since we only allow one claimer to exist at a time.
    760   if (device_claimer_->name() != claimer_name) {
    761     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
    762                           "Invalid claimer name " + claimer_name +
    763                           ". Claimer " + device_claimer_->name() +
    764                           " already exist");
    765     return;
    766   }
    767 
    768   // Release the device from the claimer. Error should be populated by the
    769   // claimer if it failed to release the given device.
    770   device_claimer_->Release(device_name, error);
    771 
    772   // Reset claimer if this is not the default claimer and no more devices are
    773   // claimed by this claimer.
    774   if (!device_claimer_->default_claimer() &&
    775       !device_claimer_->DevicesClaimed()) {
    776     device_claimer_.reset();
    777     *claimer_removed = true;
    778   }
    779 }
    780 
    781 #if !defined(DISABLE_WIFI) && defined(__BRILLO__)
    782 bool Manager::SetupApModeInterface(string* out_interface_name, Error* error) {
    783   string interface_name = wifi_driver_hal_->SetupApModeInterface();
    784   if (interface_name.empty()) {
    785     Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed,
    786                           "Failed to setup AP mode interface");
    787     return false;
    788   }
    789   *out_interface_name = interface_name;
    790   return true;
    791 }
    792 
    793 bool Manager::SetupStationModeInterface(string* out_interface_name,
    794                                         Error* error) {
    795   string interface_name = wifi_driver_hal_->SetupStationModeInterface();
    796   if (interface_name.empty()) {
    797     Error::PopulateAndLog(FROM_HERE, error, Error::kOperationFailed,
    798                           "Failed to setup station mode interface");
    799     return false;
    800   }
    801   *out_interface_name = interface_name;
    802   return true;
    803 }
    804 
    805 void Manager::OnApModeSetterVanished() {
    806   // Restore station mode interface.
    807   string interface_name = wifi_driver_hal_->SetupStationModeInterface();
    808   if (interface_name.empty()) {
    809     LOG(ERROR) << "Failed to restore station mode interface";
    810   }
    811 }
    812 #endif  // !DISABLE_WIFI && __BRILLO__
    813 
    814 void Manager::RemoveService(const ServiceRefPtr& service) {
    815   LOG(INFO) << __func__ << " for service " << service->unique_name();
    816   if (!IsServiceEphemeral(service)) {
    817     service->profile()->AbandonService(service);
    818     if (MatchProfileWithService(service)) {
    819       // We found another profile to adopt the service; no need to unload.
    820       UpdateService(service);
    821       return;
    822     }
    823   }
    824   auto service_it = std::find(services_.begin(), services_.end(), service);
    825   CHECK(service_it != services_.end());
    826   if (!UnloadService(&service_it)) {
    827     UpdateService(service);
    828   }
    829   SortServices();
    830 }
    831 
    832 bool Manager::HandleProfileEntryDeletion(const ProfileRefPtr& profile,
    833                                          const std::string& entry_name) {
    834   bool moved_services = false;
    835   for (auto it = services_.begin(); it != services_.end();) {
    836     if ((*it)->profile().get() == profile.get() &&
    837         (*it)->GetStorageIdentifier() == entry_name) {
    838       profile->AbandonService(*it);
    839       if (MatchProfileWithService(*it) ||
    840           !UnloadService(&it)) {
    841         ++it;
    842       }
    843       moved_services = true;
    844     } else {
    845       ++it;
    846     }
    847   }
    848   if (moved_services) {
    849     SortServices();
    850   }
    851   return moved_services;
    852 }
    853 
    854 map<string, string> Manager::GetLoadableProfileEntriesForService(
    855     const ServiceConstRefPtr& service) {
    856   map<string, string> profile_entries;
    857   for (const auto& profile : profiles_) {
    858     string entry_name = service->GetLoadableStorageIdentifier(
    859         *profile->GetConstStorage());
    860     if (!entry_name.empty()) {
    861       profile_entries[profile->GetRpcIdentifier()] = entry_name;
    862     }
    863   }
    864   return profile_entries;
    865 }
    866 
    867 ServiceRefPtr Manager::GetServiceWithStorageIdentifier(
    868     const ProfileRefPtr& profile, const std::string& entry_name, Error* error) {
    869   for (const auto& service : services_) {
    870     if (service->profile().get() == profile.get() &&
    871         service->GetStorageIdentifier() == entry_name) {
    872       return service;
    873     }
    874   }
    875 
    876   SLOG(this, 2) << "Entry " << entry_name
    877                 << " is not registered in the manager";
    878   return nullptr;
    879 }
    880 
    881 ServiceRefPtr Manager::CreateTemporaryServiceFromProfile(
    882     const ProfileRefPtr& profile, const std::string& entry_name, Error* error) {
    883   Technology::Identifier technology =
    884       Technology::IdentifierFromStorageGroup(entry_name);
    885   if (technology == Technology::kUnknown) {
    886     Error::PopulateAndLog(
    887         FROM_HERE, error, Error::kInternalError,
    888         "Could not determine technology for entry: " + entry_name);
    889     return nullptr;
    890   }
    891 
    892   ServiceRefPtr service = nullptr;
    893   // Since there is no provider for Ethernet services (Ethernet services are
    894   // created/provided by the Ethernet device), we will explicitly create
    895   // temporary Ethernet services for loading Ethernet entries.
    896   if (technology == Technology::kEthernet) {
    897     service = new EthernetTemporaryService(control_interface_,
    898                                            dispatcher_,
    899                                            metrics_,
    900                                            this,
    901                                            entry_name);
    902   } else if (ContainsKey(providers_, technology)) {
    903     service =
    904         providers_[technology]->CreateTemporaryServiceFromProfile(
    905             profile, entry_name, error);
    906   }
    907 
    908   if (!service) {
    909     Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
    910                           kErrorUnsupportedServiceType);
    911     return nullptr;
    912   }
    913 
    914   profile->LoadService(service);
    915   return service;
    916 }
    917 
    918 ServiceRefPtr Manager::GetServiceWithGUID(
    919     const std::string& guid, Error* error) {
    920   for (const auto& service : services_) {
    921     if (service->guid() == guid) {
    922       return service;
    923     }
    924   }
    925 
    926   string error_string(
    927       StringPrintf("Service wth GUID %s is not registered in the manager",
    928                    guid.c_str()));
    929   if (error) {
    930     error->Populate(Error::kNotFound, error_string);
    931   }
    932   SLOG(this, 2) << error_string;
    933   return nullptr;
    934 }
    935 
    936 ServiceRefPtr Manager::GetDefaultService() const {
    937   SLOG(this, 2) << __func__;
    938   if (services_.empty() || !services_[0]->connection().get()) {
    939     SLOG(this, 2) << "In " << __func__ << ": No default connection exists.";
    940     return nullptr;
    941   }
    942   return services_[0];
    943 }
    944 
    945 RpcIdentifier Manager::GetDefaultServiceRpcIdentifier(Error* /*error*/) {
    946   ServiceRefPtr default_service = GetDefaultService();
    947   return default_service ? default_service->GetRpcIdentifier() :
    948       control_interface_->NullRPCIdentifier();
    949 }
    950 
    951 bool Manager::IsTechnologyInList(const string& technology_list,
    952                                  Technology::Identifier tech) const {
    953   if (technology_list.empty())
    954     return false;
    955 
    956   Error error;
    957   vector<Technology::Identifier> technologies;
    958   return Technology::GetTechnologyVectorFromString(technology_list,
    959                                                    &technologies,
    960                                                    &error) &&
    961       std::find(technologies.begin(), technologies.end(), tech) !=
    962           technologies.end();
    963 }
    964 
    965 bool Manager::IsPortalDetectionEnabled(Technology::Identifier tech) {
    966   return IsTechnologyInList(GetCheckPortalList(nullptr), tech);
    967 }
    968 
    969 void Manager::SetStartupPortalList(const string& portal_list) {
    970   startup_portal_list_ = portal_list;
    971   use_startup_portal_list_ = true;
    972 }
    973 
    974 bool Manager::IsProfileBefore(const ProfileRefPtr& a,
    975                               const ProfileRefPtr& b) const {
    976   DCHECK(a != b);
    977   for (const auto& profile : profiles_) {
    978     if (profile == a) {
    979       return true;
    980     }
    981     if (profile == b) {
    982       return false;
    983     }
    984   }
    985   NOTREACHED() << "We should have found both profiles in the profiles_ list!";
    986   return false;
    987 }
    988 
    989 bool Manager::IsServiceEphemeral(const ServiceConstRefPtr& service) const {
    990   return service->profile() == ephemeral_profile_;
    991 }
    992 
    993 bool Manager::IsTechnologyLinkMonitorEnabled(
    994     Technology::Identifier technology) const {
    995   return IsTechnologyInList(props_.link_monitor_technologies, technology);
    996 }
    997 
    998 bool Manager::IsTechnologyAutoConnectDisabled(
    999     Technology::Identifier technology) const {
   1000   return IsTechnologyInList(props_.no_auto_connect_technologies, technology);
   1001 }
   1002 
   1003 bool Manager::IsTechnologyProhibited(
   1004     Technology::Identifier technology) const {
   1005   return IsTechnologyInList(props_.prohibited_technologies, technology);
   1006 }
   1007 
   1008 void Manager::OnProfileStorageInitialized(Profile* profile) {
   1009 #if !defined(DISABLE_WIFI)
   1010   wifi_provider_->LoadAndFixupServiceEntries(profile);
   1011 #endif  // DISABLE_WIFI
   1012 }
   1013 
   1014 DeviceRefPtr Manager::GetEnabledDeviceWithTechnology(
   1015     Technology::Identifier technology) const {
   1016   for (const auto& device : FilterByTechnology(technology)) {
   1017     if (device->enabled()) {
   1018       return device;
   1019     }
   1020   }
   1021   return nullptr;
   1022 }
   1023 
   1024 DeviceRefPtr Manager::GetEnabledDeviceByLinkName(
   1025     const string& link_name) const {
   1026   for (const auto& device : devices_) {
   1027     if (device->link_name() == link_name) {
   1028       if (!device->enabled()) {
   1029         return nullptr;
   1030       }
   1031       return device;
   1032     }
   1033   }
   1034   return nullptr;
   1035 }
   1036 
   1037 const ProfileRefPtr& Manager::ActiveProfile() const {
   1038   DCHECK_NE(profiles_.size(), 0U);
   1039   return profiles_.back();
   1040 }
   1041 
   1042 bool Manager::IsActiveProfile(const ProfileRefPtr& profile) const {
   1043   return (profiles_.size() > 0 &&
   1044           ActiveProfile().get() == profile.get());
   1045 }
   1046 
   1047 bool Manager::MoveServiceToProfile(const ServiceRefPtr& to_move,
   1048                                    const ProfileRefPtr& destination) {
   1049   const ProfileRefPtr from = to_move->profile();
   1050   SLOG(this, 2) << "Moving service "
   1051                 << to_move->unique_name()
   1052                 << " to profile "
   1053                 << destination->GetFriendlyName()
   1054                 << " from "
   1055                 << from->GetFriendlyName();
   1056   return destination->AdoptService(to_move) && from->AbandonService(to_move);
   1057 }
   1058 
   1059 ProfileRefPtr Manager::LookupProfileByRpcIdentifier(
   1060     const string& profile_rpcid) {
   1061   for (const auto& profile : profiles_) {
   1062     if (profile_rpcid == profile->GetRpcIdentifier()) {
   1063       return profile;
   1064     }
   1065   }
   1066   return nullptr;
   1067 }
   1068 
   1069 void Manager::SetProfileForService(const ServiceRefPtr& to_set,
   1070                                    const string& profile_rpcid,
   1071                                    Error* error) {
   1072   ProfileRefPtr profile = LookupProfileByRpcIdentifier(profile_rpcid);
   1073   if (!profile) {
   1074     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
   1075                           StringPrintf("Unknown Profile %s requested for "
   1076                                        "Service", profile_rpcid.c_str()));
   1077     return;
   1078   }
   1079 
   1080   if (!to_set->profile()) {
   1081     // We are being asked to set the profile property of a service that
   1082     // has never been registered.  Now is a good time to register it.
   1083     RegisterService(to_set);
   1084   }
   1085 
   1086   if (to_set->profile().get() == profile.get()) {
   1087     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
   1088                           "Service is already connected to this profile");
   1089   } else if (!MoveServiceToProfile(to_set, profile)) {
   1090     Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError,
   1091                           "Unable to move service to profile");
   1092   }
   1093 }
   1094 
   1095 void Manager::SetEnabledStateForTechnology(const std::string& technology_name,
   1096                                            bool enabled_state,
   1097                                            bool persist,
   1098                                            Error* error,
   1099                                            const ResultCallback& callback) {
   1100   CHECK(error);
   1101   DCHECK(error->IsOngoing());
   1102   Technology::Identifier id = Technology::IdentifierFromName(technology_name);
   1103   if (id == Technology::kUnknown) {
   1104     error->Populate(Error::kInvalidArguments, "Unknown technology");
   1105     return;
   1106   }
   1107   if (enabled_state && IsTechnologyProhibited(id)) {
   1108     error->Populate(Error::kPermissionDenied,
   1109                     "The " + technology_name + " technology is prohibited");
   1110     return;
   1111   }
   1112   bool deferred = false;
   1113   auto result_aggregator(make_scoped_refptr(new ResultAggregator(callback)));
   1114   for (auto& device : devices_) {
   1115     if (device->technology() != id)
   1116       continue;
   1117 
   1118     Error device_error(Error::kOperationInitiated);
   1119     ResultCallback aggregator_callback(
   1120         Bind(&ResultAggregator::ReportResult, result_aggregator));
   1121     if (persist) {
   1122       device->SetEnabledPersistent(
   1123           enabled_state, &device_error, aggregator_callback);
   1124     } else {
   1125       device->SetEnabledNonPersistent(
   1126           enabled_state, &device_error, aggregator_callback);
   1127     }
   1128     if (device_error.IsOngoing()) {
   1129       deferred = true;
   1130     } else if (!error->IsFailure()) {  // Report first failure.
   1131       error->CopyFrom(device_error);
   1132     }
   1133   }
   1134   if (deferred) {
   1135     // Some device is handling this change asynchronously. Clobber any error
   1136     // from another device, so that we can indicate the operation is still in
   1137     // progress.
   1138     error->Populate(Error::kOperationInitiated);
   1139   } else if (error->IsOngoing()) {
   1140     // |error| IsOngoing at entry to this method, but no device
   1141     // |deferred|. Reset |error|, to indicate we're done.
   1142     error->Reset();
   1143   }
   1144 }
   1145 
   1146 void Manager::UpdateEnabledTechnologies() {
   1147   Error error;
   1148   adaptor_->EmitStringsChanged(kEnabledTechnologiesProperty,
   1149                                EnabledTechnologies(&error));
   1150 }
   1151 
   1152 void Manager::UpdateUninitializedTechnologies() {
   1153   Error error;
   1154   adaptor_->EmitStringsChanged(kUninitializedTechnologiesProperty,
   1155                                UninitializedTechnologies(&error));
   1156 }
   1157 
   1158 void Manager::SetPassiveMode() {
   1159   CHECK(!device_claimer_);
   1160   // Create a default device claimer to claim devices from  shill as they're
   1161   // detected.  Devices will be managed by remote application, which will use
   1162   // the default claimer to specify the devices for shill to manage.
   1163   device_claimer_.reset(
   1164       new DeviceClaimer(kDefaultClaimerName, &device_info_, true));
   1165 }
   1166 
   1167 void Manager::SetIgnoreUnknownEthernet(bool ignore) {
   1168   LOG(INFO) << __func__ << "(" << ignore << ")";
   1169   ignore_unknown_ethernet_ = ignore;
   1170 }
   1171 
   1172 void Manager::SetPrependDNSServers(const std::string& prepend_dns_servers) {
   1173   props_.prepend_dns_servers = prepend_dns_servers;
   1174 }
   1175 
   1176 void Manager::SetAcceptHostnameFrom(const string& hostname_from) {
   1177   accept_hostname_from_ = hostname_from;
   1178 }
   1179 
   1180 bool Manager::ShouldAcceptHostnameFrom(const string& device_name) const {
   1181   return base::MatchPattern(device_name, accept_hostname_from_);
   1182 }
   1183 
   1184 void Manager::SetDHCPv6EnabledDevices(const vector<string>& device_list) {
   1185   dhcpv6_enabled_devices_ = device_list;
   1186 }
   1187 
   1188 bool Manager::IsDHCPv6EnabledForDevice(const string& device_name) const {
   1189   return std::find(dhcpv6_enabled_devices_.begin(),
   1190                    dhcpv6_enabled_devices_.end(),
   1191                    device_name) != dhcpv6_enabled_devices_.end();
   1192 }
   1193 
   1194 vector<string> Manager::FilterPrependDNSServersByFamily(
   1195     IPAddress::Family family) const {
   1196   vector<string> dns_servers;
   1197   vector<string> split_servers = base::SplitString(
   1198       props_.prepend_dns_servers, ",", base::TRIM_WHITESPACE,
   1199       base::SPLIT_WANT_ALL);
   1200   for (const auto& server : split_servers) {
   1201     const IPAddress address(server);
   1202     if (address.family() == family) {
   1203       dns_servers.push_back(server);
   1204     }
   1205   }
   1206   return dns_servers;
   1207 }
   1208 
   1209 bool Manager::IsSuspending() {
   1210   if (power_manager_ && power_manager_->suspending()) {
   1211     return true;
   1212   }
   1213   return false;
   1214 }
   1215 
   1216 void Manager::RecordDarkResumeWakeReason(const string& wake_reason) {
   1217   power_manager_->RecordDarkResumeWakeReason(wake_reason);
   1218 }
   1219 
   1220 void Manager::RegisterDevice(const DeviceRefPtr& to_manage) {
   1221   LOG(INFO) << "Device " << to_manage->FriendlyName() << " registered.";
   1222   // Manager is running in passive mode when default claimer is created, which
   1223   // means devices are being managed by remote application. Only manage the
   1224   // device if it was explicitly released by remote application through
   1225   // default claimer.
   1226   if (device_claimer_ && device_claimer_->default_claimer()) {
   1227     if (!device_claimer_->IsDeviceReleased(to_manage->link_name())) {
   1228       Error error;
   1229       device_claimer_->Claim(to_manage->link_name(), &error);
   1230       return;
   1231     }
   1232   }
   1233 
   1234   for (const auto& device : devices_) {
   1235     if (to_manage == device)
   1236       return;
   1237   }
   1238   devices_.push_back(to_manage);
   1239 
   1240   LoadDeviceFromProfiles(to_manage);
   1241 
   1242   if (IsTechnologyProhibited(to_manage->technology())) {
   1243     Error unused_error;
   1244     to_manage->SetEnabledNonPersistent(false, &unused_error, ResultCallback());
   1245   }
   1246 
   1247   // If |to_manage| is new, it needs to be persisted.
   1248   UpdateDevice(to_manage);
   1249 
   1250   // In normal usage, running_ will always be true when we are here, however
   1251   // unit tests sometimes do things in otherwise invalid states.
   1252   if (running_ && (to_manage->enabled_persistent() ||
   1253                    to_manage->IsUnderlyingDeviceEnabled()))
   1254     to_manage->SetEnabled(true);
   1255 
   1256   EmitDeviceProperties();
   1257 }
   1258 
   1259 void Manager::DeregisterDevice(const DeviceRefPtr& to_forget) {
   1260   SLOG(this, 2) << __func__ << "(" << to_forget->FriendlyName() << ")";
   1261   for (auto it = devices_.begin(); it != devices_.end(); ++it) {
   1262     if (to_forget.get() == it->get()) {
   1263       SLOG(this, 2) << "Deregistered device: " << to_forget->UniqueName();
   1264       UpdateDevice(to_forget);
   1265       to_forget->SetEnabled(false);
   1266       devices_.erase(it);
   1267       EmitDeviceProperties();
   1268       return;
   1269     }
   1270   }
   1271   SLOG(this, 2) << __func__ << " unknown device: "
   1272                 << to_forget->UniqueName();
   1273 }
   1274 
   1275 void Manager::DeregisterDeviceByLinkName(const string& link_name) {
   1276   for (const auto& device : devices_) {
   1277     if (device->link_name() == link_name) {
   1278       DeregisterDevice(device);
   1279       break;
   1280     }
   1281   }
   1282 }
   1283 
   1284 vector<string> Manager::ClaimedDevices(Error* error) {
   1285   vector<string> results;
   1286   if (!device_claimer_) {
   1287     return results;
   1288   }
   1289 
   1290   const auto& devices = device_claimer_->claimed_device_names();
   1291   results.resize(devices.size());
   1292   std::copy(devices.begin(), devices.end(), results.begin());
   1293   return results;
   1294 }
   1295 
   1296 void Manager::LoadDeviceFromProfiles(const DeviceRefPtr& device) {
   1297   // We are applying device properties from the DefaultProfile, and adding the
   1298   // union of hidden services in all loaded profiles to the device.
   1299   for (const auto& profile : profiles_) {
   1300     // Load device configuration, if any exists, as well as hidden services.
   1301     profile->ConfigureDevice(device);
   1302   }
   1303 }
   1304 
   1305 void Manager::EmitDeviceProperties() {
   1306   Error error;
   1307   vector<string> device_paths = EnumerateDevices(&error);
   1308   adaptor_->EmitRpcIdentifierArrayChanged(kDevicesProperty,
   1309                                           device_paths);
   1310   adaptor_->EmitStringsChanged(kAvailableTechnologiesProperty,
   1311                                AvailableTechnologies(&error));
   1312   adaptor_->EmitStringsChanged(kEnabledTechnologiesProperty,
   1313                                EnabledTechnologies(&error));
   1314   adaptor_->EmitStringsChanged(kUninitializedTechnologiesProperty,
   1315                                UninitializedTechnologies(&error));
   1316 }
   1317 
   1318 void Manager::OnInnerDevicesChanged() {
   1319   EmitDeviceProperties();
   1320 }
   1321 
   1322 void Manager::OnDeviceClaimerVanished() {
   1323   // Reset device claimer.
   1324   device_claimer_.reset();
   1325 }
   1326 
   1327 #if !defined(DISABLE_WIFI)
   1328 bool Manager::SetDisableWiFiVHT(const bool& disable_wifi_vht, Error* error) {
   1329   if (disable_wifi_vht == wifi_provider_->disable_vht()) {
   1330     return false;
   1331   }
   1332   wifi_provider_->set_disable_vht(disable_wifi_vht);
   1333   return true;
   1334 }
   1335 
   1336 bool Manager::GetDisableWiFiVHT(Error* error) {
   1337   return wifi_provider_->disable_vht();
   1338 }
   1339 #endif  // DISABLE_WIFI
   1340 
   1341 bool Manager::SetProhibitedTechnologies(const string& prohibited_technologies,
   1342                                         Error* error) {
   1343   vector<Technology::Identifier> technology_vector;
   1344   if (!Technology::GetTechnologyVectorFromString(prohibited_technologies,
   1345                                                  &technology_vector,
   1346                                                  error)) {
   1347     return false;
   1348   }
   1349   for (const auto& technology : technology_vector) {
   1350     Error unused_error(Error::kOperationInitiated);
   1351     ResultCallback result_callback(Bind(
   1352         &Manager::OnTechnologyProhibited, Unretained(this), technology));
   1353     const bool kPersistentSave = false;
   1354     SetEnabledStateForTechnology(Technology::NameFromIdentifier(technology),
   1355                                  false,
   1356                                  kPersistentSave,
   1357                                  &unused_error,
   1358                                  result_callback);
   1359   }
   1360   props_.prohibited_technologies = prohibited_technologies;
   1361 
   1362   return true;
   1363 }
   1364 
   1365 void Manager::OnTechnologyProhibited(Technology::Identifier technology,
   1366                                      const Error& error) {
   1367   SLOG(this, 2) << __func__ << " for "
   1368                 << Technology::NameFromIdentifier(technology);
   1369 }
   1370 
   1371 string Manager::GetProhibitedTechnologies(Error* error) {
   1372   return props_.prohibited_technologies;
   1373 }
   1374 
   1375 bool Manager::HasService(const ServiceRefPtr& service) {
   1376   for (const auto& manager_service : services_) {
   1377     if (manager_service->unique_name() == service->unique_name())
   1378       return true;
   1379   }
   1380   return false;
   1381 }
   1382 
   1383 void Manager::RegisterService(const ServiceRefPtr& to_manage) {
   1384   SLOG(this, 2) << "Registering service " << to_manage->unique_name();
   1385 
   1386   MatchProfileWithService(to_manage);
   1387 
   1388   // Now add to OUR list.
   1389   for (const auto& service : services_) {
   1390     CHECK(to_manage->unique_name() != service->unique_name());
   1391   }
   1392   services_.push_back(to_manage);
   1393   SortServices();
   1394 }
   1395 
   1396 void Manager::DeregisterService(const ServiceRefPtr& to_forget) {
   1397   for (auto it = services_.begin(); it != services_.end(); ++it) {
   1398     if (to_forget->unique_name() == (*it)->unique_name()) {
   1399       DLOG_IF(FATAL, (*it)->connection())
   1400           << "Service " << (*it)->unique_name()
   1401           << " still has a connection (in call to " << __func__ << ")";
   1402       (*it)->Unload();
   1403       (*it)->SetProfile(nullptr);
   1404       services_.erase(it);
   1405       SortServices();
   1406       return;
   1407     }
   1408   }
   1409 }
   1410 
   1411 bool Manager::UnloadService(vector<ServiceRefPtr>::iterator* service_iterator) {
   1412   if (!(**service_iterator)->Unload()) {
   1413     return false;
   1414   }
   1415 
   1416   DCHECK(!(**service_iterator)->connection());
   1417   (**service_iterator)->SetProfile(nullptr);
   1418   *service_iterator = services_.erase(*service_iterator);
   1419 
   1420   return true;
   1421 }
   1422 
   1423 void Manager::UpdateService(const ServiceRefPtr& to_update) {
   1424   CHECK(to_update);
   1425   bool is_interesting_state_change = false;
   1426   const auto& state_it = watched_service_states_.find(to_update->unique_name());
   1427   if (state_it != watched_service_states_.end()) {
   1428     is_interesting_state_change = (to_update->state() != state_it->second);
   1429   } else {
   1430     is_interesting_state_change = to_update->IsActive(nullptr);
   1431   }
   1432 
   1433   string log_message = StringPrintf(
   1434       "Service %s updated; state: %s failure %s",
   1435       to_update->unique_name().c_str(),
   1436       Service::ConnectStateToString(to_update->state()),
   1437       Service::ConnectFailureToString(to_update->failure()));
   1438   if (is_interesting_state_change) {
   1439     LOG(INFO) << log_message;
   1440   } else {
   1441     SLOG(this, 2) << log_message;
   1442   }
   1443   SLOG(this, 2) << "IsConnected(): " << to_update->IsConnected();
   1444   SLOG(this, 2) << "IsConnecting(): " << to_update->IsConnecting();
   1445   if (to_update->IsConnected()) {
   1446     to_update->EnableAndRetainAutoConnect();
   1447     // Persists the updated auto_connect setting in the profile.
   1448     SaveServiceToProfile(to_update);
   1449   }
   1450   SortServices();
   1451 }
   1452 
   1453 void Manager::UpdateDevice(const DeviceRefPtr& to_update) {
   1454   LOG(INFO) << "Device " << to_update->link_name() << " updated: "
   1455             << (to_update->enabled_persistent() ? "enabled" : "disabled");
   1456   // Saves the device to the topmost profile that accepts it (ordinary
   1457   // profiles don't update but default profiles do). Normally, the topmost
   1458   // updating profile would be the DefaultProfile at the bottom of the stack.
   1459   // Autotests, differ from the normal scenario, however, in that they push a
   1460   // second test-only DefaultProfile.
   1461   for (auto rit = profiles_.rbegin(); rit != profiles_.rend(); ++rit) {
   1462     if ((*rit)->UpdateDevice(to_update)) {
   1463       return;
   1464     }
   1465   }
   1466 }
   1467 
   1468 #if !defined(DISABLE_WIFI)
   1469 void Manager::UpdateWiFiProvider() {
   1470   // Saves |wifi_provider_| to the topmost profile that accepts it (ordinary
   1471   // profiles don't update but default profiles do). Normally, the topmost
   1472   // updating profile would be the DefaultProfile at the bottom of the stack.
   1473   // Autotests, differ from the normal scenario, however, in that they push a
   1474   // second test-only DefaultProfile.
   1475   for (auto rit = profiles_.rbegin(); rit != profiles_.rend(); ++rit) {
   1476     if ((*rit)->UpdateWiFiProvider(*wifi_provider_)) {
   1477       return;
   1478     }
   1479   }
   1480 }
   1481 #endif  // DISABLE_WIFI
   1482 
   1483 void Manager::SaveServiceToProfile(const ServiceRefPtr& to_update) {
   1484   if (IsServiceEphemeral(to_update)) {
   1485     if (profiles_.empty()) {
   1486       LOG(ERROR) << "Cannot assign profile to service: no profiles exist!";
   1487     } else {
   1488       MoveServiceToProfile(to_update, profiles_.back());
   1489     }
   1490   } else {
   1491     to_update->profile()->UpdateService(to_update);
   1492   }
   1493 }
   1494 
   1495 void Manager::LoadProperties(const scoped_refptr<DefaultProfile>& profile) {
   1496   profile->LoadManagerProperties(&props_, dhcp_properties_.get());
   1497   SetIgnoredDNSSearchPaths(props_.ignored_dns_search_paths, nullptr);
   1498 }
   1499 
   1500 void Manager::AddTerminationAction(const string& name,
   1501                                    const base::Closure& start) {
   1502   termination_actions_.Add(name, start);
   1503 }
   1504 
   1505 void Manager::TerminationActionComplete(const string& name) {
   1506   SLOG(this, 2) << __func__;
   1507   termination_actions_.ActionComplete(name);
   1508 }
   1509 
   1510 void Manager::RemoveTerminationAction(const string& name) {
   1511   SLOG(this, 2) << __func__;
   1512   termination_actions_.Remove(name);
   1513 }
   1514 
   1515 void Manager::RunTerminationActions(const ResultCallback& done_callback) {
   1516   LOG(INFO) << "Running termination actions.";
   1517   termination_actions_.Run(kTerminationActionsTimeoutMilliseconds,
   1518                            done_callback);
   1519 }
   1520 
   1521 bool Manager::RunTerminationActionsAndNotifyMetrics(
   1522     const ResultCallback& done_callback) {
   1523   if (termination_actions_.IsEmpty())
   1524     return false;
   1525 
   1526   metrics_->NotifyTerminationActionsStarted();
   1527   RunTerminationActions(done_callback);
   1528   return true;
   1529 }
   1530 
   1531 int Manager::RegisterDefaultServiceCallback(const ServiceCallback& callback) {
   1532   default_service_callbacks_[++default_service_callback_tag_] = callback;
   1533   return default_service_callback_tag_;
   1534 }
   1535 
   1536 void Manager::DeregisterDefaultServiceCallback(int tag) {
   1537   default_service_callbacks_.erase(tag);
   1538 }
   1539 
   1540 #if !defined(DISABLE_WIFI)
   1541 void Manager::VerifyDestination(const string& certificate,
   1542                                 const string& public_key,
   1543                                 const string& nonce,
   1544                                 const string& signed_data,
   1545                                 const string& destination_udn,
   1546                                 const string& hotspot_ssid,
   1547                                 const string& hotspot_bssid,
   1548                                 const ResultBoolCallback& cb,
   1549                                 Error* error) {
   1550   if (hotspot_bssid.length() > 32) {
   1551     error->Populate(Error::kOperationFailed,
   1552                     "Invalid SSID given for verification.");
   1553     return;
   1554   }
   1555   vector<uint8_t> ssid;
   1556   string bssid;
   1557   if (hotspot_ssid.length() || hotspot_bssid.length()) {
   1558     // If Chrome thinks this destination is already configured, service
   1559     // will be an AP that both we and the destination are connected
   1560     // to, and not the thing we should verify against.
   1561     ssid.assign(hotspot_ssid.begin(), hotspot_ssid.end());
   1562     bssid = hotspot_bssid;
   1563   } else {
   1564     // For now, we only support a single connected WiFi service.  If we change
   1565     // that, we'll need to revisit this.
   1566     bool found_one = false;
   1567     for (const auto& service : services_) {
   1568       if (service->technology() == Technology::kWifi &&
   1569           service->IsConnected()) {
   1570         WiFiService* wifi = reinterpret_cast<WiFiService*>(&(*service));
   1571         bssid = wifi->bssid();
   1572         ssid = wifi->ssid();
   1573         found_one = true;
   1574         break;
   1575       }
   1576     }
   1577     if (!found_one) {
   1578       error->Populate(Error::kOperationFailed,
   1579                       "Unable to find connected WiFi service.");
   1580       return;
   1581     }
   1582   }
   1583   crypto_util_proxy_->VerifyDestination(certificate, public_key, nonce,
   1584                                         signed_data, destination_udn,
   1585                                         ssid, bssid, cb, error);
   1586 }
   1587 
   1588 void Manager::VerifyToEncryptLink(string public_key,
   1589                                   string data,
   1590                                   ResultStringCallback cb,
   1591                                   const Error& error,
   1592                                   bool success) {
   1593   if (!success || !error.IsSuccess()) {
   1594     CHECK(error.IsFailure()) << "Return code from CryptoUtilProxy "
   1595                              << "inconsistent with error code.";
   1596     cb.Run(error, "");
   1597     return;
   1598   }
   1599   Error encrypt_error;
   1600   if (!crypto_util_proxy_->EncryptData(public_key, data, cb, &encrypt_error)) {
   1601     CHECK(encrypt_error.IsFailure()) << "CryptoUtilProxy::EncryptData returned "
   1602                                      << "inconsistently.";
   1603     cb.Run(encrypt_error, "");
   1604   }
   1605 }
   1606 
   1607 void Manager::VerifyAndEncryptData(const string& certificate,
   1608                                    const string& public_key,
   1609                                    const string& nonce,
   1610                                    const string& signed_data,
   1611                                    const string& destination_udn,
   1612                                    const string& hotspot_ssid,
   1613                                    const string& hotspot_bssid,
   1614                                    const string& data,
   1615                                    const ResultStringCallback& cb,
   1616                                    Error* error) {
   1617   ResultBoolCallback on_verification_success = Bind(
   1618       &Manager::VerifyToEncryptLink, AsWeakPtr(), public_key, data, cb);
   1619   VerifyDestination(certificate, public_key, nonce, signed_data,
   1620                     destination_udn, hotspot_ssid, hotspot_bssid,
   1621                     on_verification_success, error);
   1622 }
   1623 
   1624 void Manager::VerifyAndEncryptCredentials(const string& certificate,
   1625                                           const string& public_key,
   1626                                           const string& nonce,
   1627                                           const string& signed_data,
   1628                                           const string& destination_udn,
   1629                                           const string& hotspot_ssid,
   1630                                           const string& hotspot_bssid,
   1631                                           const string& network_path,
   1632                                           const ResultStringCallback& cb,
   1633                                           Error* error) {
   1634   // This is intentionally left unimplemented until we have a security review.
   1635   error->Populate(Error::kNotImplemented, "Not implemented");
   1636 }
   1637 #endif  // DISABLE_WIFI
   1638 
   1639 int Manager::CalcConnectionId(std::string gateway_ip,
   1640                               std::string gateway_mac) {
   1641   return static_cast<int>(std::hash<std::string>()(gateway_ip + gateway_mac +
   1642       std::to_string(props_.connection_id_salt)));
   1643 }
   1644 
   1645 void Manager::ReportServicesOnSameNetwork(int connection_id) {
   1646   int num_services = 0;
   1647   for (const auto& service : services_) {
   1648     if (service->connection_id() == connection_id) {
   1649       num_services++;
   1650     }
   1651   }
   1652   metrics_->NotifyServicesOnSameNetwork(num_services);
   1653 }
   1654 
   1655 void Manager::NotifyDefaultServiceChanged(const ServiceRefPtr& service) {
   1656   for (const auto& callback : default_service_callbacks_) {
   1657     callback.second.Run(service);
   1658   }
   1659   metrics_->NotifyDefaultServiceChanged(service.get());
   1660   EmitDefaultService();
   1661 }
   1662 
   1663 void Manager::EmitDefaultService() {
   1664   RpcIdentifier rpc_identifier = GetDefaultServiceRpcIdentifier(nullptr);
   1665   if (rpc_identifier != default_service_rpc_identifier_) {
   1666     adaptor_->EmitRpcIdentifierChanged(kDefaultServiceProperty, rpc_identifier);
   1667     default_service_rpc_identifier_ = rpc_identifier;
   1668   }
   1669 }
   1670 
   1671 void Manager::OnSuspendImminent() {
   1672   metrics_->NotifySuspendActionsStarted();
   1673   if (devices_.empty()) {
   1674     // If there are no devices, then suspend actions succeeded synchronously.
   1675     // Make a call to the Manager::OnSuspendActionsComplete directly, since
   1676     // result_aggregator will not.
   1677     OnSuspendActionsComplete(Error(Error::kSuccess));
   1678     return;
   1679   }
   1680   auto result_aggregator(make_scoped_refptr(new ResultAggregator(
   1681       Bind(&Manager::OnSuspendActionsComplete, AsWeakPtr()), dispatcher_,
   1682       kTerminationActionsTimeoutMilliseconds)));
   1683   for (const auto& device : devices_) {
   1684     ResultCallback aggregator_callback(
   1685         Bind(&ResultAggregator::ReportResult, result_aggregator));
   1686     device->OnBeforeSuspend(aggregator_callback);
   1687   }
   1688 }
   1689 
   1690 void Manager::OnSuspendDone() {
   1691   metrics_->NotifySuspendDone();
   1692   // Un-suppress auto-connect in case this flag was left set in dark resume.
   1693   set_suppress_autoconnect(false);
   1694   for (const auto& service : services_) {
   1695     service->OnAfterResume();
   1696   }
   1697   SortServices();
   1698   for (const auto& device : devices_) {
   1699     device->OnAfterResume();
   1700   }
   1701 }
   1702 
   1703 void Manager::OnDarkSuspendImminent() {
   1704   metrics_->NotifyDarkResumeActionsStarted();
   1705   if (devices_.empty()) {
   1706     // If there are no devices, then suspend actions succeeded synchronously.
   1707     // Make a call to the Manager::OnDarkResumeActionsComplete directly, since
   1708     // result_aggregator will not.
   1709     OnDarkResumeActionsComplete(Error(Error::kSuccess));
   1710     return;
   1711   }
   1712   auto result_aggregator(make_scoped_refptr(new ResultAggregator(
   1713       Bind(&Manager::OnDarkResumeActionsComplete, AsWeakPtr()), dispatcher_,
   1714       kTerminationActionsTimeoutMilliseconds)));
   1715   for (const auto& device : devices_) {
   1716     ResultCallback aggregator_callback(
   1717         Bind(&ResultAggregator::ReportResult, result_aggregator));
   1718     device->OnDarkResume(aggregator_callback);
   1719   }
   1720 }
   1721 
   1722 void Manager::OnSuspendActionsComplete(const Error& error) {
   1723   LOG(INFO) << "Finished suspend actions. Result: " << error;
   1724   metrics_->NotifySuspendActionsCompleted(error.IsSuccess());
   1725   power_manager_->ReportSuspendReadiness();
   1726 }
   1727 
   1728 void Manager::OnDarkResumeActionsComplete(const Error& error) {
   1729   LOG(INFO) << "Finished dark resume actions. Result: " << error;
   1730   metrics_->NotifyDarkResumeActionsCompleted(error.IsSuccess());
   1731   power_manager_->ReportDarkSuspendReadiness();
   1732 }
   1733 
   1734 
   1735 vector<DeviceRefPtr>
   1736 Manager::FilterByTechnology(Technology::Identifier tech) const {
   1737   vector<DeviceRefPtr> found;
   1738   for (const auto& device : devices_) {
   1739     if (device->technology() == tech)
   1740       found.push_back(device);
   1741   }
   1742   return found;
   1743 }
   1744 
   1745 ServiceRefPtr Manager::FindService(const string& name) {
   1746   for (const auto& service : services_) {
   1747     if (name == service->unique_name())
   1748       return service;
   1749   }
   1750   return nullptr;
   1751 }
   1752 
   1753 void Manager::HelpRegisterConstDerivedRpcIdentifier(
   1754     const string& name,
   1755     RpcIdentifier(Manager::*get)(Error* error)) {
   1756   store_.RegisterDerivedRpcIdentifier(
   1757       name,
   1758       RpcIdentifierAccessor(
   1759           new CustomAccessor<Manager, RpcIdentifier>(this, get, nullptr)));
   1760 }
   1761 
   1762 void Manager::HelpRegisterConstDerivedRpcIdentifiers(
   1763     const string& name,
   1764     RpcIdentifiers(Manager::*get)(Error* error)) {
   1765   store_.RegisterDerivedRpcIdentifiers(
   1766       name,
   1767       RpcIdentifiersAccessor(
   1768           new CustomAccessor<Manager, RpcIdentifiers>(this, get, nullptr)));
   1769 }
   1770 
   1771 void Manager::HelpRegisterDerivedString(
   1772     const string& name,
   1773     string(Manager::*get)(Error* error),
   1774     bool(Manager::*set)(const string&, Error*)) {
   1775   store_.RegisterDerivedString(
   1776       name,
   1777       StringAccessor(new CustomAccessor<Manager, string>(this, get, set)));
   1778 }
   1779 
   1780 void Manager::HelpRegisterConstDerivedStrings(
   1781     const string& name,
   1782     Strings(Manager::*get)(Error*)) {
   1783   store_.RegisterDerivedStrings(
   1784       name, StringsAccessor(
   1785                 new CustomAccessor<Manager, Strings>(this, get, nullptr)));
   1786 }
   1787 
   1788 void Manager::HelpRegisterDerivedBool(
   1789     const string& name,
   1790     bool(Manager::*get)(Error* error),
   1791     bool(Manager::*set)(const bool&, Error*)) {
   1792   store_.RegisterDerivedBool(
   1793       name,
   1794       BoolAccessor(new CustomAccessor<Manager, bool>(this, get, set, nullptr)));
   1795 }
   1796 
   1797 void Manager::SortServices() {
   1798   // We might be called in the middle of a series of events that
   1799   // may result in multiple calls to Manager::SortServices, or within
   1800   // an outer loop that may also be traversing the services_ list.
   1801   // Defer this work to the event loop.
   1802   if (sort_services_task_.IsCancelled()) {
   1803     sort_services_task_.Reset(Bind(&Manager::SortServicesTask, AsWeakPtr()));
   1804     dispatcher_->PostTask(sort_services_task_.callback());
   1805   }
   1806 }
   1807 
   1808 void Manager::SortServicesTask() {
   1809   SLOG(this, 4) << "In " << __func__;
   1810   sort_services_task_.Cancel();
   1811   ServiceRefPtr default_service;
   1812 
   1813   if (!services_.empty()) {
   1814     // Keep track of the service that is the candidate for the default
   1815     // service.  We have not yet tested to see if this service has a
   1816     // connection.
   1817     default_service = services_[0];
   1818   }
   1819   const bool kCompareConnectivityState = true;
   1820   sort(services_.begin(), services_.end(),
   1821        ServiceSorter(this, kCompareConnectivityState, technology_order_));
   1822 
   1823   if (!services_.empty()) {
   1824     ConnectionRefPtr default_connection = default_service->connection();
   1825     if (default_connection &&
   1826         services_[0]->connection() != default_connection) {
   1827       default_connection->SetIsDefault(false);
   1828     }
   1829     if (services_[0]->connection()) {
   1830       services_[0]->connection()->SetIsDefault(true);
   1831       if (default_service != services_[0]) {
   1832         default_service = services_[0];
   1833         LOG(INFO) << "Default service is now "
   1834                   << default_service->unique_name();
   1835       }
   1836     } else {
   1837       default_service = nullptr;
   1838     }
   1839   }
   1840 
   1841   Error error;
   1842   adaptor_->EmitRpcIdentifierArrayChanged(kServiceCompleteListProperty,
   1843                                           EnumerateCompleteServices(nullptr));
   1844   adaptor_->EmitRpcIdentifierArrayChanged(kServicesProperty,
   1845                                           EnumerateAvailableServices(nullptr));
   1846   adaptor_->EmitRpcIdentifierArrayChanged(kServiceWatchListProperty,
   1847                                           EnumerateWatchedServices(nullptr));
   1848   adaptor_->EmitStringsChanged(kConnectedTechnologiesProperty,
   1849                                ConnectedTechnologies(&error));
   1850   adaptor_->EmitStringChanged(kDefaultTechnologyProperty,
   1851                               DefaultTechnology(&error));
   1852   NotifyDefaultServiceChanged(default_service);
   1853   RefreshConnectionState();
   1854   DetectMultiHomedDevices();
   1855 
   1856   AutoConnect();
   1857 }
   1858 
   1859 void Manager::DeviceStatusCheckTask() {
   1860   SLOG(this, 4) << "In " << __func__;
   1861 
   1862   ConnectionStatusCheck();
   1863   DevicePresenceStatusCheck();
   1864 
   1865   dispatcher_->PostDelayedTask(device_status_check_task_.callback(),
   1866                                kDeviceStatusCheckIntervalMilliseconds);
   1867 }
   1868 
   1869 void Manager::ConnectionStatusCheck() {
   1870   SLOG(this, 4) << "In " << __func__;
   1871   // Report current connection status.
   1872   Metrics::ConnectionStatus status = Metrics::kConnectionStatusOffline;
   1873   if (IsConnected()) {
   1874     status = Metrics::kConnectionStatusConnected;
   1875     // Check if device is online as well.
   1876     if (IsOnline()) {
   1877       metrics_->NotifyDeviceConnectionStatus(Metrics::kConnectionStatusOnline);
   1878     }
   1879   }
   1880   metrics_->NotifyDeviceConnectionStatus(status);
   1881 }
   1882 
   1883 void Manager::DevicePresenceStatusCheck() {
   1884   Error error;
   1885   vector<string> available_technologies = AvailableTechnologies(&error);
   1886 
   1887   for (const auto& technology : kProbeTechnologies) {
   1888     bool presence = std::find(available_technologies.begin(),
   1889                               available_technologies.end(),
   1890                               technology) != available_technologies.end();
   1891     metrics_->NotifyDevicePresenceStatus(
   1892         Technology::IdentifierFromName(technology), presence);
   1893   }
   1894 }
   1895 
   1896 bool Manager::MatchProfileWithService(const ServiceRefPtr& service) {
   1897   vector<ProfileRefPtr>::reverse_iterator it;
   1898   for (it = profiles_.rbegin(); it != profiles_.rend(); ++it) {
   1899     if ((*it)->ConfigureService(service)) {
   1900       break;
   1901     }
   1902   }
   1903   if (it == profiles_.rend()) {
   1904     ephemeral_profile_->AdoptService(service);
   1905     return false;
   1906   }
   1907   return true;
   1908 }
   1909 
   1910 void Manager::AutoConnect() {
   1911   if (suppress_autoconnect_) {
   1912     LOG(INFO) << "Auto-connect suppressed -- explicitly suppressed.";
   1913     return;
   1914   }
   1915   if (!running_) {
   1916     LOG(INFO) << "Auto-connect suppressed -- not running.";
   1917     return;
   1918   }
   1919   if (power_manager_ && power_manager_->suspending() &&
   1920       !power_manager_->in_dark_resume()) {
   1921     LOG(INFO) << "Auto-connect suppressed -- system is suspending.";
   1922     return;
   1923   }
   1924   if (services_.empty()) {
   1925     LOG(INFO) << "Auto-connect suppressed -- no services.";
   1926     return;
   1927   }
   1928 
   1929   if (SLOG_IS_ON(Manager, 4)) {
   1930     SLOG(this, 4) << "Sorted service list for AutoConnect: ";
   1931     for (size_t i = 0; i < services_.size(); ++i) {
   1932       ServiceRefPtr service = services_[i];
   1933       const char* compare_reason = nullptr;
   1934       if (i + 1 < services_.size()) {
   1935         const bool kCompareConnectivityState = true;
   1936         Service::Compare(
   1937             this, service, services_[i+1], kCompareConnectivityState,
   1938             technology_order_, &compare_reason);
   1939       } else {
   1940         compare_reason = "last";
   1941       }
   1942       SLOG(this, 4) << "Service " << service->unique_name()
   1943                     << " Profile: " << service->profile()->GetFriendlyName()
   1944                     << " IsConnected: " << service->IsConnected()
   1945                     << " IsConnecting: " << service->IsConnecting()
   1946                     << " HasEverConnected: " << service->has_ever_connected()
   1947                     << " IsFailed: " << service->IsFailed()
   1948                     << " connectable: " << service->connectable()
   1949                     << " auto_connect: " << service->auto_connect()
   1950                     << " retain_auto_connect: "
   1951                     << service->retain_auto_connect()
   1952                     << " priority: " << service->priority()
   1953                     << " crypto_algorithm: " << service->crypto_algorithm()
   1954                     << " key_rotation: " << service->key_rotation()
   1955                     << " endpoint_auth: " << service->endpoint_auth()
   1956                     << " strength: " << service->strength()
   1957                     << " sorted: " << compare_reason;
   1958     }
   1959   }
   1960 
   1961 #if !defined(DISABLE_WIFI)
   1962   // Report the number of auto-connectable wifi services available when wifi is
   1963   // idle (no active or pending connection), which will trigger auto connect
   1964   // for wifi services.
   1965   if (IsWifiIdle()) {
   1966     wifi_provider_->ReportAutoConnectableServices();
   1967   }
   1968 #endif  // DISABLE_WIFI
   1969 
   1970   // Perform auto-connect.
   1971   for (const auto& service : services_) {
   1972     if (service->auto_connect()) {
   1973       service->AutoConnect();
   1974     }
   1975   }
   1976 }
   1977 
   1978 void Manager::ConnectToBestServices(Error* /*error*/) {
   1979   dispatcher_->PostTask(Bind(&Manager::ConnectToBestServicesTask, AsWeakPtr()));
   1980 }
   1981 
   1982 void Manager::ConnectToBestServicesTask() {
   1983   vector<ServiceRefPtr> services_copy = services_;
   1984   const bool kCompareConnectivityState = false;
   1985   sort(services_copy.begin(), services_copy.end(),
   1986        ServiceSorter(this, kCompareConnectivityState, technology_order_));
   1987   set<Technology::Identifier> connecting_technologies;
   1988   for (const auto& service : services_copy) {
   1989     if (!service->connectable()) {
   1990       // Due to service sort order, it is guaranteed that no services beyond
   1991       // this one will be connectable either.
   1992       break;
   1993     }
   1994     if (!service->auto_connect() || !service->IsVisible()) {
   1995       continue;
   1996     }
   1997     Technology::Identifier technology = service->technology();
   1998     if (!Technology::IsPrimaryConnectivityTechnology(technology) &&
   1999         !IsConnected()) {
   2000       // Non-primary services need some other service connected first.
   2001       continue;
   2002     }
   2003     if (ContainsKey(connecting_technologies, technology)) {
   2004       // We have already started a connection for this technology.
   2005       continue;
   2006     }
   2007     if (service->explicitly_disconnected())
   2008       continue;
   2009     connecting_technologies.insert(technology);
   2010     if (!service->IsConnected() && !service->IsConnecting()) {
   2011       // At first blush, it may seem that using Service::AutoConnect might
   2012       // be the right choice, however Service::IsAutoConnectable and its
   2013       // overridden implementations consider a host of conditions which
   2014       // prevent it from attempting a connection which we'd like to ignore
   2015       // for the purposes of this user-initiated action.
   2016       Error error;
   2017       service->Connect(&error, __func__);
   2018       if (error.IsFailure()) {
   2019         LOG(ERROR) << "Connection failed: " << error.message();
   2020       }
   2021     }
   2022   }
   2023 
   2024   if (SLOG_IS_ON(Manager, 4)) {
   2025     SLOG(this, 4) << "Sorted service list for ConnectToBestServicesTask: ";
   2026     for (size_t i = 0; i < services_copy.size(); ++i) {
   2027       ServiceRefPtr service = services_copy[i];
   2028       const char* compare_reason = nullptr;
   2029       if (i + 1 < services_copy.size()) {
   2030         if (!service->connectable()) {
   2031           // Due to service sort order, it is guaranteed that no services beyond
   2032           // this one are connectable either.
   2033           break;
   2034         }
   2035         Service::Compare(
   2036             this, service, services_copy[i+1],
   2037             kCompareConnectivityState, technology_order_,
   2038             &compare_reason);
   2039       } else {
   2040         compare_reason = "last";
   2041       }
   2042       SLOG(this, 4) << "Service " << service->unique_name()
   2043                     << " Profile: " << service->profile()->GetFriendlyName()
   2044                     << " IsConnected: " << service->IsConnected()
   2045                     << " IsConnecting: " << service->IsConnecting()
   2046                     << " HasEverConnected: " << service->has_ever_connected()
   2047                     << " IsFailed: " << service->IsFailed()
   2048                     << " connectable: " << service->connectable()
   2049                     << " auto_connect: " << service->auto_connect()
   2050                     << " retain_auto_connect: "
   2051                     << service->retain_auto_connect()
   2052                     << " priority: " << service->priority()
   2053                     << " crypto_algorithm: " << service->crypto_algorithm()
   2054                     << " key_rotation: " << service->key_rotation()
   2055                     << " endpoint_auth: " << service->endpoint_auth()
   2056                     << " strength: " << service->strength()
   2057                     << " sorted: " << compare_reason;
   2058     }
   2059   }
   2060 }
   2061 
   2062 void Manager::CreateConnectivityReport(Error* /*error*/) {
   2063   LOG(INFO) << "Creating Connectivity Report";
   2064 
   2065   // For each of the connected services, perform a single portal detection
   2066   // test to assess connectivity.  The results should be written to the log.
   2067   for (const auto& service : services_) {
   2068     if (!service->IsConnected()) {
   2069       // Service sort order guarantees that no service beyond this one will be
   2070       // connected either.
   2071       break;
   2072     }
   2073     // Get the underlying device for this service and perform connectivity test.
   2074     for (const auto& device : devices_) {
   2075       if (device->IsConnectedToService(service)) {
   2076         if (device->StartConnectivityTest()) {
   2077           SLOG(this, 3) << "Started connectivity test for service "
   2078                         << service->unique_name();
   2079         } else {
   2080           SLOG(this, 3) << "Failed to start connectivity test for service "
   2081                         << service->unique_name()
   2082                            << " device not reporting IsConnected.";
   2083         }
   2084         break;
   2085       }
   2086     }
   2087   }
   2088 }
   2089 
   2090 bool Manager::IsConnected() const {
   2091   // |services_| is sorted such that connected services are first.
   2092   return !services_.empty() && services_.front()->IsConnected();
   2093 }
   2094 
   2095 bool Manager::IsOnline() const {
   2096   // |services_| is sorted such that online services are first.
   2097   return !services_.empty() && services_.front()->IsOnline();
   2098 }
   2099 
   2100 string Manager::CalculateState(Error* /*error*/) {
   2101   return IsConnected() ? kStateOnline : kStateOffline;
   2102 }
   2103 
   2104 void Manager::RefreshConnectionState() {
   2105   const ServiceRefPtr& service = GetDefaultService();
   2106   string connection_state = service ? service->GetStateString() : kStateIdle;
   2107   if (connection_state_ == connection_state) {
   2108     return;
   2109   }
   2110   connection_state_ = connection_state;
   2111   adaptor_->EmitStringChanged(kConnectionStateProperty, connection_state_);
   2112   // Send upstart notifications for the initial idle state
   2113   // and when we transition in/out of connected states.
   2114   if ((!is_connected_state_) && (IsConnected())) {
   2115       is_connected_state_ = true;
   2116       upstart_->NotifyConnected();
   2117   } else if ((is_connected_state_) && (!IsConnected())) {
   2118       is_connected_state_ = false;
   2119       upstart_->NotifyDisconnected();
   2120   } else if (connection_state_ == kStateIdle) {
   2121       upstart_->NotifyDisconnected();
   2122   }
   2123 }
   2124 
   2125 vector<string> Manager::AvailableTechnologies(Error* /*error*/) {
   2126   set<string> unique_technologies;
   2127   for (const auto& device : devices_) {
   2128     unique_technologies.insert(
   2129         Technology::NameFromIdentifier(device->technology()));
   2130   }
   2131   return vector<string>(unique_technologies.begin(), unique_technologies.end());
   2132 }
   2133 
   2134 vector<string> Manager::ConnectedTechnologies(Error* /*error*/) {
   2135   set<string> unique_technologies;
   2136   for (const auto& device : devices_) {
   2137     if (device->IsConnected())
   2138       unique_technologies.insert(
   2139           Technology::NameFromIdentifier(device->technology()));
   2140   }
   2141   return vector<string>(unique_technologies.begin(), unique_technologies.end());
   2142 }
   2143 
   2144 bool Manager::IsTechnologyConnected(Technology::Identifier technology) const {
   2145   for (const auto& device : devices_) {
   2146     if (device->technology() == technology && device->IsConnected())
   2147       return true;
   2148   }
   2149   return false;
   2150 }
   2151 
   2152 string Manager::DefaultTechnology(Error* /*error*/) {
   2153   return (!services_.empty() && services_[0]->IsConnected()) ?
   2154       services_[0]->GetTechnologyString() : "";
   2155 }
   2156 
   2157 vector<string> Manager::EnabledTechnologies(Error* /*error*/) {
   2158   set<string> unique_technologies;
   2159   for (const auto& device : devices_) {
   2160     if (device->enabled())
   2161       unique_technologies.insert(
   2162           Technology::NameFromIdentifier(device->technology()));
   2163   }
   2164   return vector<string>(unique_technologies.begin(), unique_technologies.end());
   2165 }
   2166 
   2167 vector<string> Manager::UninitializedTechnologies(Error* /*error*/) {
   2168   return device_info_.GetUninitializedTechnologies();
   2169 }
   2170 
   2171 RpcIdentifiers Manager::EnumerateDevices(Error* /*error*/) {
   2172   RpcIdentifiers device_rpc_ids;
   2173   for (const auto& device : devices_) {
   2174     device_rpc_ids.push_back(device->GetRpcIdentifier());
   2175   }
   2176   // Enumerate devices that are internal to the services, such as PPPoE devices.
   2177   for (const auto& service : services_) {
   2178     if (!service->GetInnerDeviceRpcIdentifier().empty()) {
   2179       device_rpc_ids.push_back(service->GetInnerDeviceRpcIdentifier());
   2180     }
   2181   }
   2182   return device_rpc_ids;
   2183 }
   2184 
   2185 RpcIdentifiers Manager::EnumerateProfiles(Error* /*error*/) {
   2186   RpcIdentifiers profile_rpc_ids;
   2187   for (const auto& profile : profiles_) {
   2188     profile_rpc_ids.push_back(profile->GetRpcIdentifier());
   2189   }
   2190   return profile_rpc_ids;
   2191 }
   2192 
   2193 RpcIdentifiers Manager::EnumerateAvailableServices(Error* /*error*/) {
   2194   RpcIdentifiers service_rpc_ids;
   2195   for (const auto& service : services_) {
   2196     if (service->IsVisible()) {
   2197       service_rpc_ids.push_back(service->GetRpcIdentifier());
   2198     }
   2199   }
   2200   return service_rpc_ids;
   2201 }
   2202 
   2203 RpcIdentifiers Manager::EnumerateCompleteServices(Error* /*error*/) {
   2204   RpcIdentifiers service_rpc_ids;
   2205   for (const auto& service : services_) {
   2206     service_rpc_ids.push_back(service->GetRpcIdentifier());
   2207   }
   2208   return service_rpc_ids;
   2209 }
   2210 
   2211 RpcIdentifiers Manager::EnumerateWatchedServices(Error* /*error*/) {
   2212   RpcIdentifiers service_rpc_ids;
   2213   watched_service_states_.clear();
   2214   for (const auto& service : services_) {
   2215     if (service->IsVisible() && service->IsActive(nullptr)) {
   2216       service_rpc_ids.push_back(service->GetRpcIdentifier());
   2217       watched_service_states_[service->unique_name()] = service->state();
   2218     }
   2219   }
   2220   return service_rpc_ids;
   2221 }
   2222 
   2223 string Manager::GetActiveProfileRpcIdentifier(Error* /*error*/) {
   2224   return ActiveProfile()->GetRpcIdentifier();
   2225 }
   2226 
   2227 string Manager::GetCheckPortalList(Error* /*error*/) {
   2228   return use_startup_portal_list_ ? startup_portal_list_ :
   2229       props_.check_portal_list;
   2230 }
   2231 
   2232 bool Manager::SetCheckPortalList(const string& portal_list, Error* error) {
   2233   use_startup_portal_list_ = false;
   2234   if (props_.check_portal_list == portal_list) {
   2235     return false;
   2236   }
   2237   props_.check_portal_list = portal_list;
   2238   return true;
   2239 }
   2240 
   2241 string Manager::GetIgnoredDNSSearchPaths(Error* /*error*/) {
   2242   return props_.ignored_dns_search_paths;
   2243 }
   2244 
   2245 bool Manager::SetIgnoredDNSSearchPaths(const string& ignored_paths,
   2246                                        Error* /*error*/) {
   2247   if (props_.ignored_dns_search_paths == ignored_paths) {
   2248     return false;
   2249   }
   2250   vector<string> ignored_path_list;
   2251   if (!ignored_paths.empty()) {
   2252     ignored_path_list = base::SplitString(
   2253         ignored_paths, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
   2254   }
   2255   props_.ignored_dns_search_paths = ignored_paths;
   2256   resolver_->set_ignored_search_list(ignored_path_list);
   2257   return true;
   2258 }
   2259 
   2260 // called via RPC (e.g., from ManagerDBusAdaptor)
   2261 ServiceRefPtr Manager::GetService(const KeyValueStore& args, Error* error) {
   2262   if (args.ContainsString(kTypeProperty) &&
   2263       args.GetString(kTypeProperty) == kTypeVPN) {
   2264      // GetService on a VPN service should actually perform ConfigureService.
   2265      // TODO(pstew): Remove this hack and change Chrome to use ConfigureService
   2266      // instead, when we no longer need to support flimflam.  crbug.com/213802
   2267      return ConfigureService(args, error);
   2268   }
   2269 
   2270   ServiceRefPtr service = GetServiceInner(args, error);
   2271   if (service) {
   2272     // Configures the service using the rest of the passed-in arguments.
   2273     service->Configure(args, error);
   2274   }
   2275 
   2276   return service;
   2277 }
   2278 
   2279 ServiceRefPtr Manager::GetServiceInner(const KeyValueStore& args,
   2280                                        Error* error) {
   2281   if (args.ContainsString(kGuidProperty)) {
   2282     SLOG(this, 2) << __func__ << ": searching by GUID";
   2283     ServiceRefPtr service =
   2284         GetServiceWithGUID(args.GetString(kGuidProperty), nullptr);
   2285     if (service) {
   2286       return service;
   2287     }
   2288   }
   2289 
   2290   if (!args.ContainsString(kTypeProperty)) {
   2291     Error::PopulateAndLog(
   2292         FROM_HERE, error, Error::kInvalidArguments, kErrorTypeRequired);
   2293     return nullptr;
   2294   }
   2295 
   2296   string type = args.GetString(kTypeProperty);
   2297   Technology::Identifier technology = Technology::IdentifierFromName(type);
   2298   if (!ContainsKey(providers_, technology)) {
   2299     Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
   2300                           kErrorUnsupportedServiceType);
   2301     return nullptr;
   2302   }
   2303 
   2304   SLOG(this, 2) << __func__ << ": getting " << type << " Service";
   2305   return providers_[technology]->GetService(args, error);
   2306 }
   2307 
   2308 // called via RPC (e.g., from ManagerDBusAdaptor)
   2309 ServiceRefPtr Manager::ConfigureService(const KeyValueStore& args,
   2310                                         Error* error) {
   2311   ProfileRefPtr profile = ActiveProfile();
   2312   bool profile_specified = args.ContainsString(kProfileProperty);
   2313   if (profile_specified) {
   2314     string profile_rpcid = args.GetString(kProfileProperty);
   2315     profile = LookupProfileByRpcIdentifier(profile_rpcid);
   2316     if (!profile) {
   2317       Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
   2318                             "Invalid profile name " + profile_rpcid);
   2319       return nullptr;
   2320     }
   2321   }
   2322 
   2323   ServiceRefPtr service = GetServiceInner(args, error);
   2324   if (error->IsFailure() || !service) {
   2325     LOG(ERROR) << "GetService failed; returning upstream error.";
   2326     return nullptr;
   2327   }
   2328 
   2329   // First pull in any stored configuration associated with the service.
   2330   if (service->profile() == profile) {
   2331     SLOG(this, 2) << __func__ << ": service " << service->unique_name()
   2332                   << " is already a member of profile "
   2333                      << profile->GetFriendlyName()
   2334                      << " so a load is not necessary.";
   2335   } else if (profile->LoadService(service)) {
   2336     SLOG(this, 2) << __func__ << ": applied stored information from profile "
   2337                   << profile->GetFriendlyName()
   2338                   << " into service "
   2339                   << service->unique_name();
   2340   } else {
   2341     SLOG(this, 2) << __func__ << ": no previous information in profile "
   2342                   << profile->GetFriendlyName()
   2343                   << " exists for service "
   2344                   << service->unique_name();
   2345   }
   2346 
   2347   // Overlay this with the passed-in configuration parameters.
   2348   service->Configure(args, error);
   2349 
   2350   // Overwrite the profile data with the resulting configured service.
   2351   if (!profile->UpdateService(service)) {
   2352     Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError,
   2353                           "Unable to save service to profile");
   2354     return nullptr;
   2355   }
   2356 
   2357   if (HasService(service)) {
   2358     // If the service has been registered (it may not be -- as is the case
   2359     // with invisible WiFi networks), we can now transfer the service between
   2360     // profiles.
   2361     if (IsServiceEphemeral(service) ||
   2362         (profile_specified && service->profile() != profile)) {
   2363       SLOG(this, 2) << "Moving service to profile "
   2364                     << profile->GetFriendlyName();
   2365       if (!MoveServiceToProfile(service, profile)) {
   2366         Error::PopulateAndLog(FROM_HERE, error, Error::kInternalError,
   2367                               "Unable to move service to profile");
   2368       }
   2369     }
   2370   }
   2371 
   2372   // Notify the service that a profile has been configured for it.
   2373   service->OnProfileConfigured();
   2374 
   2375   return service;
   2376 }
   2377 
   2378 // called via RPC (e.g., from ManagerDBusAdaptor)
   2379 ServiceRefPtr Manager::ConfigureServiceForProfile(
   2380     const string& profile_rpcid, const KeyValueStore& args, Error* error) {
   2381   if (!args.ContainsString(kTypeProperty)) {
   2382     Error::PopulateAndLog(
   2383         FROM_HERE, error, Error::kInvalidArguments, kErrorTypeRequired);
   2384     return nullptr;
   2385   }
   2386 
   2387   string type = args.GetString(kTypeProperty);
   2388   Technology::Identifier technology = Technology::IdentifierFromName(type);
   2389 
   2390   if (!ContainsKey(providers_, technology)) {
   2391     Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
   2392                           kErrorUnsupportedServiceType);
   2393     return nullptr;
   2394   }
   2395 
   2396   ProviderInterface* provider = providers_[technology];
   2397 
   2398   ProfileRefPtr profile = LookupProfileByRpcIdentifier(profile_rpcid);
   2399   if (!profile) {
   2400     Error::PopulateAndLog(FROM_HERE, error, Error::kNotFound,
   2401                           "Profile specified was not found");
   2402     return nullptr;
   2403   }
   2404   if (args.LookupString(kProfileProperty, profile_rpcid) != profile_rpcid) {
   2405     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
   2406                           "Profile argument does not match that in "
   2407                           "the configuration arguments");
   2408     return nullptr;
   2409   }
   2410 
   2411   ServiceRefPtr service;
   2412   if (args.ContainsString(kGuidProperty)) {
   2413     SLOG(this, 2) << __func__ << ": searching by GUID";
   2414     service = GetServiceWithGUID(args.GetString(kGuidProperty), nullptr);
   2415     if (service && service->technology() != technology) {
   2416       Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
   2417                             StringPrintf("This GUID matches a non-%s service",
   2418                                          type.c_str()));
   2419       return nullptr;
   2420     }
   2421   }
   2422 
   2423   if (!service) {
   2424     Error find_error;
   2425     service = provider->FindSimilarService(args, &find_error);
   2426   }
   2427 
   2428   // If no matching service exists, create a new service in the specified
   2429   // profile using ConfigureService().
   2430   if (!service) {
   2431     KeyValueStore configure_args;
   2432     configure_args.CopyFrom(args);
   2433     configure_args.SetString(kProfileProperty, profile_rpcid);
   2434     return ConfigureService(configure_args, error);
   2435   }
   2436 
   2437   // The service already exists and is set to the desired profile,
   2438   // the service is in the ephemeral profile, or the current profile
   2439   // for the service appears before the desired profile, we need to
   2440   // reassign the service to the new profile if necessary, leaving
   2441   // the old profile intact (i.e, not calling Profile::AbandonService()).
   2442   // Then, configure the properties on the service as well as its newly
   2443   // associated profile.
   2444   if (service->profile() == profile ||
   2445       IsServiceEphemeral(service) ||
   2446       IsProfileBefore(service->profile(), profile)) {
   2447     SetupServiceInProfile(service, profile, args, error);
   2448     return service;
   2449   }
   2450 
   2451   // The current profile for the service appears after the desired
   2452   // profile.  We must create a temporary service specifically for
   2453   // the task of creating configuration data.  This service will
   2454   // neither inherit properties from the visible service, nor will
   2455   // it exist after this function returns.
   2456   service = provider->CreateTemporaryService(args, error);
   2457   if (!service || !error->IsSuccess()) {
   2458     // Service::CreateTemporaryService() failed, and has set the error
   2459     // appropriately.
   2460     return nullptr;
   2461   }
   2462 
   2463   // The profile may already have configuration for this service.
   2464   profile->ConfigureService(service);
   2465 
   2466   SetupServiceInProfile(service, profile, args, error);
   2467 
   2468   // Although we have succeeded, this service will not exist, so its
   2469   // path is of no use to the caller.
   2470   DCHECK(service->HasOneRef());
   2471   return nullptr;
   2472 }
   2473 
   2474 void Manager::SetupServiceInProfile(ServiceRefPtr service,
   2475                                     ProfileRefPtr profile,
   2476                                     const KeyValueStore& args,
   2477                                     Error* error) {
   2478   service->SetProfile(profile);
   2479   service->Configure(args, error);
   2480   profile->UpdateService(service);
   2481 }
   2482 
   2483 ServiceRefPtr Manager::FindMatchingService(const KeyValueStore& args,
   2484                                            Error* error) {
   2485   for (const auto& service : services_) {
   2486     if (service->DoPropertiesMatch(args)) {
   2487       return service;
   2488     }
   2489   }
   2490   error->Populate(Error::kNotFound, "Matching service was not found");
   2491   return nullptr;
   2492 }
   2493 
   2494 const map<string, GeolocationInfos>
   2495     &Manager::GetNetworksForGeolocation() const {
   2496   return networks_for_geolocation_;
   2497 }
   2498 
   2499 void Manager::OnDeviceGeolocationInfoUpdated(const DeviceRefPtr& device) {
   2500   SLOG(this, 2) << __func__ << " for technology "
   2501                 << Technology::NameFromIdentifier(device->technology());
   2502   switch (device->technology()) {
   2503     // TODO(gauravsh): crbug.com/217833 Need a strategy for combining
   2504     // geolocation objects from multiple devices of the same technolgy.
   2505     // Currently, we just override the any previously acquired
   2506     // geolocation objects for the retrieved technology type.
   2507     case Technology::kWifi:
   2508       networks_for_geolocation_[kGeoWifiAccessPointsProperty] =
   2509           device->GetGeolocationObjects();
   2510       break;
   2511     case Technology::kCellular:
   2512       networks_for_geolocation_[kGeoCellTowersProperty] =
   2513           device->GetGeolocationObjects();
   2514       break;
   2515     default:
   2516       // Ignore other technologies.
   2517       break;
   2518   }
   2519 }
   2520 
   2521 void Manager::RecheckPortal(Error* /*error*/) {
   2522   for (const auto& device : devices_) {
   2523     if (device->RequestPortalDetection()) {
   2524       // Only start Portal Detection on the device with the default connection.
   2525       // We will get a "true" return value when we've found that device, and
   2526       // can end our loop early as a result.
   2527       break;
   2528     }
   2529   }
   2530 }
   2531 
   2532 void Manager::RecheckPortalOnService(const ServiceRefPtr& service) {
   2533   for (const auto& device : devices_) {
   2534     if (device->IsConnectedToService(service)) {
   2535       // As opposed to RecheckPortal() above, we explicitly stop and then
   2536       // restart portal detection, since the service to recheck was explicitly
   2537       // specified.
   2538       device->RestartPortalDetection();
   2539       break;
   2540     }
   2541   }
   2542 }
   2543 
   2544 void Manager::RequestScan(Device::ScanType scan_type,
   2545                           const string& technology, Error* error) {
   2546   if (technology == kTypeWifi || technology == "") {
   2547     for (const auto& wifi_device : FilterByTechnology(Technology::kWifi)) {
   2548       metrics_->NotifyUserInitiatedEvent(Metrics::kUserInitiatedEventWifiScan);
   2549       wifi_device->Scan(scan_type, error, __func__);
   2550     }
   2551   } else {
   2552     // TODO(quiche): support scanning for other technologies?
   2553     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
   2554                           "Unrecognized technology " + technology);
   2555   }
   2556 }
   2557 
   2558 void Manager::SetSchedScan(bool enable, Error* error) {
   2559   for (const auto& wifi_device : FilterByTechnology(Technology::kWifi)) {
   2560     wifi_device->SetSchedScan(enable, error);
   2561   }
   2562 }
   2563 
   2564 string Manager::GetTechnologyOrder() {
   2565   vector<string> technology_names;
   2566   for (const auto& technology : technology_order_) {
   2567     technology_names.push_back(Technology::NameFromIdentifier(technology));
   2568   }
   2569 
   2570   return base::JoinString(technology_names, ",");
   2571 }
   2572 
   2573 void Manager::SetTechnologyOrder(const string& order, Error* error) {
   2574   vector<Technology::Identifier> new_order;
   2575   SLOG(this, 2) << "Setting technology order to " << order;
   2576   if (!Technology::GetTechnologyVectorFromString(order, &new_order, error)) {
   2577     return;
   2578   }
   2579 
   2580   technology_order_ = new_order;
   2581   if (running_) {
   2582     SortServices();
   2583   }
   2584 }
   2585 
   2586 bool Manager::IsWifiIdle() {
   2587   bool ret = false;
   2588 
   2589   // Since services are sorted by connection state, status of the wifi device
   2590   // can be determine by examing the connection state of the first wifi service.
   2591   for (const auto& service : services_) {
   2592     if (service->technology() == Technology::kWifi) {
   2593       if (!service->IsConnecting() && !service->IsConnected()) {
   2594         ret = true;
   2595       }
   2596       break;
   2597     }
   2598   }
   2599   return ret;
   2600 }
   2601 
   2602 void Manager::UpdateProviderMapping() {
   2603 #if !defined(DISABLE_WIRED_8021X)
   2604   providers_[Technology::kEthernetEap] = ethernet_eap_provider_.get();
   2605 #endif  // DISABLE_WIRED_8021X
   2606   providers_[Technology::kVPN] = vpn_provider_.get();
   2607 #if !defined(DISABLE_WIFI)
   2608   providers_[Technology::kWifi] = wifi_provider_.get();
   2609 #endif  // DISABLE_WIFI
   2610 #if !defined(DISABLE_WIMAX)
   2611   providers_[Technology::kWiMax] = wimax_provider_.get();
   2612 #endif  // DISABLE_WIMAX
   2613 }
   2614 
   2615 DeviceRefPtr Manager::GetDeviceConnectedToService(ServiceRefPtr service) {
   2616   for (DeviceRefPtr device : devices_) {
   2617     if (device->IsConnectedToService(service)) {
   2618       return device;
   2619     }
   2620   }
   2621   return nullptr;
   2622 }
   2623 
   2624 void Manager::DetectMultiHomedDevices() {
   2625   map<string, vector<DeviceRefPtr>> subnet_buckets;
   2626   for (const auto& device : devices_) {
   2627     const auto& connection = device->connection();
   2628     string subnet_name;
   2629     if (connection) {
   2630       subnet_name = connection->GetSubnetName();
   2631     }
   2632     if (subnet_name.empty()) {
   2633       device->SetIsMultiHomed(false);
   2634     } else {
   2635       subnet_buckets[subnet_name].push_back(device);
   2636     }
   2637   }
   2638 
   2639   for (const auto& subnet_bucket : subnet_buckets) {
   2640     const auto& device_list = subnet_bucket.second;
   2641     if (device_list.size() > 1) {
   2642       for (const auto& device : device_list) {
   2643         device->SetIsMultiHomed(true);
   2644       }
   2645     } else {
   2646       DCHECK_EQ(1U, device_list.size());
   2647       device_list.back()->SetIsMultiHomed(false);
   2648     }
   2649   }
   2650 }
   2651 
   2652 }  // namespace shill
   2653