Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / options / chromeos / internet_options_handler.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/webui/options/chromeos/internet_options_handler.h"
6
7 #include <ctype.h>
8
9 #include <map>
10 #include <string>
11 #include <vector>
12
13 #include "ash/system/chromeos/network/network_connect.h"
14 #include "ash/system/chromeos/network/network_icon.h"
15 #include "base/basictypes.h"
16 #include "base/bind.h"
17 #include "base/bind_helpers.h"
18 #include "base/command_line.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/values.h"
22 #include "chrome/browser/browser_process.h"
23 #include "chrome/browser/chrome_notification_types.h"
24 #include "chrome/browser/chromeos/login/user.h"
25 #include "chrome/browser/chromeos/login/user_manager.h"
26 #include "chrome/browser/chromeos/mobile_config.h"
27 #include "chrome/browser/chromeos/net/onc_utils.h"
28 #include "chrome/browser/chromeos/options/network_config_view.h"
29 #include "chrome/browser/chromeos/options/network_property_ui_data.h"
30 #include "chrome/browser/chromeos/settings/cros_settings.h"
31 #include "chrome/browser/chromeos/sim_dialog_delegate.h"
32 #include "chrome/browser/chromeos/ui/choose_mobile_network_dialog.h"
33 #include "chrome/browser/chromeos/ui/mobile_config_ui.h"
34 #include "chrome/browser/chromeos/ui_proxy_config_service.h"
35 #include "chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h"
36 #include "chrome/browser/ui/webui/options/chromeos/internet_options_handler_strings.h"
37 #include "chromeos/chromeos_switches.h"
38 #include "chromeos/network/device_state.h"
39 #include "chromeos/network/favorite_state.h"
40 #include "chromeos/network/managed_network_configuration_handler.h"
41 #include "chromeos/network/network_configuration_handler.h"
42 #include "chromeos/network/network_connection_handler.h"
43 #include "chromeos/network/network_device_handler.h"
44 #include "chromeos/network/network_event_log.h"
45 #include "chromeos/network/network_ip_config.h"
46 #include "chromeos/network/network_profile.h"
47 #include "chromeos/network/network_profile_handler.h"
48 #include "chromeos/network/network_state.h"
49 #include "chromeos/network/network_state_handler.h"
50 #include "chromeos/network/network_ui_data.h"
51 #include "chromeos/network/network_util.h"
52 #include "chromeos/network/shill_property_util.h"
53 #include "components/onc/onc_constants.h"
54 #include "content/public/browser/notification_service.h"
55 #include "content/public/browser/user_metrics.h"
56 #include "content/public/browser/web_contents.h"
57 #include "content/public/browser/web_ui.h"
58 #include "grit/ash_resources.h"
59 #include "grit/locale_settings.h"
60 #include "grit/theme_resources.h"
61 #include "third_party/cros_system_api/dbus/service_constants.h"
62 #include "ui/base/l10n/l10n_util.h"
63 #include "ui/base/layout.h"
64 #include "ui/base/resource/resource_bundle.h"
65 #include "ui/base/webui/web_ui_util.h"
66 #include "ui/gfx/image/image_skia.h"
67
68 namespace chromeos {
69 namespace options {
70
71 namespace {
72
73 // Keys for the network description dictionary passed to the web ui. Make sure
74 // to keep the strings in sync with what the JavaScript side uses.
75 const char kNetworkInfoKeyConnectable[] = "connectable";
76 const char kNetworkInfoKeyConnected[] = "connected";
77 const char kNetworkInfoKeyConnecting[] = "connecting";
78 const char kNetworkInfoKeyIconURL[] = "iconURL";
79 const char kNetworkInfoKeyNetworkName[] = "networkName";
80 const char kNetworkInfoKeyNetworkType[] = "networkType";
81 const char kNetworkInfoKeyServicePath[] = "servicePath";
82 const char kNetworkInfoKeyPolicyManaged[] = "policyManaged";
83
84 // These are keys for getting IP information from the web ui.
85 const char kIpConfigAddress[] = "address";
86 const char kIpConfigPrefixLength[] = "prefixLength";
87 const char kIpConfigNetmask[] = "netmask";
88 const char kIpConfigGateway[] = "gateway";
89 const char kIpConfigNameServers[] = "nameServers";
90 const char kIpConfigAutoConfig[] = "ipAutoConfig";
91 const char kIpConfigWebProxyAutoDiscoveryUrl[] = "webProxyAutoDiscoveryUrl";
92
93 // These are types of name server selections from the web ui.
94 const char kNameServerTypeAutomatic[] = "automatic";
95 const char kNameServerTypeGoogle[] = "google";
96 const char kNameServerTypeUser[] = "user";
97
98 // These are dictionary names used to send data to the web ui.
99 const char kDictionaryIpConfig[] = "ipconfig";
100 const char kDictionaryStaticIp[] = "staticIP";
101 const char kDictionarySavedIp[] = "savedIP";
102
103 // Google public name servers (DNS).
104 const char kGoogleNameServers[] = "8.8.4.4,8.8.8.8";
105
106 // Functions we call in JavaScript.
107 const char kRefreshNetworkDataFunction[] =
108     "options.network.NetworkList.refreshNetworkData";
109 const char kSetDefaultNetworkIconsFunction[] =
110     "options.network.NetworkList.setDefaultNetworkIcons";
111 const char kShowDetailedInfoFunction[] =
112     "options.internet.DetailsInternetPage.showDetailedInfo";
113 const char kUpdateConnectionDataFunction[] =
114     "options.internet.DetailsInternetPage.updateConnectionData";
115 const char kUpdateCarrierFunction[] =
116     "options.internet.DetailsInternetPage.updateCarrier";
117 const char kUpdateLoggedInUserTypeFunction[] =
118     "options.network.NetworkList.updateLoggedInUserType";
119 const char kUpdateSecurityTabFunction[] =
120     "options.internet.DetailsInternetPage.updateSecurityTab";
121
122 // These are used to register message handlers with JavaScript.
123 const char kBuyDataPlanMessage[] = "buyDataPlan";
124 const char kChangePinMessage[] = "changePin";
125 const char kDisableCellularMessage[] = "disableCellular";
126 const char kDisableWifiMessage[] = "disableWifi";
127 const char kDisableWimaxMessage[] = "disableWimax";
128 const char kEnableCellularMessage[] = "enableCellular";
129 const char kEnableWifiMessage[] = "enableWifi";
130 const char kEnableWimaxMessage[] = "enableWimax";
131 const char kNetworkCommandMessage[] = "networkCommand";
132 const char kRefreshNetworksMessage[] = "refreshNetworks";
133 const char kSetApnMessage[] = "setApn";
134 const char kSetAutoConnectMessage[] = "setAutoConnect";
135 const char kSetCarrierMessage[] = "setCarrier";
136 const char kSetIPConfigMessage[] = "setIPConfig";
137 const char kSetPreferNetworkMessage[] = "setPreferNetwork";
138 const char kSetServerHostname[] = "setServerHostname";
139 const char kSetSimCardLockMessage[] = "setSimCardLock";
140 const char kShowMorePlanInfoMessage[] = "showMorePlanInfo";
141
142 // These are strings used to communicate with JavaScript.
143 const char kTagActivate[] = "activate";
144 const char kTagActivationState[] = "activationState";
145 const char kTagAddConnection[] = "add";
146 const char kTagApn[] = "apn";
147 const char kTagAutoConnect[] = "autoConnect";
148 const char kTagBssid[] = "bssid";
149 const char kTagCarrierSelectFlag[] = "showCarrierSelect";
150 const char kTagCarrierUrl[] = "carrierUrl";
151 const char kTagCellular[] = "cellular";
152 const char kTagCellularAvailable[] = "cellularAvailable";
153 const char kTagCellularEnabled[] = "cellularEnabled";
154 const char kTagCellularSupportsScan[] = "cellularSupportsScan";
155 const char kTagConfigure[] = "configure";
156 const char kTagConnect[] = "connect";
157 const char kTagConnected[] = "connected";
158 const char kTagConnecting[] = "connecting";
159 const char kTagConnectionState[] = "connectionState";
160 const char kTagControlledBy[] = "controlledBy";
161 const char kTagDeviceConnected[] = "deviceConnected";
162 const char kTagDisableConnectButton[] = "disableConnectButton";
163 const char kTagDisconnect[] = "disconnect";
164 const char kTagEncryption[] = "encryption";
165 const char kTagErrorState[] = "errorState";
166 const char kTagEsn[] = "esn";
167 const char kTagFirmwareRevision[] = "firmwareRevision";
168 const char kTagForget[] = "forget";
169 const char kTagFrequency[] = "frequency";
170 const char kTagGsm[] = "gsm";
171 const char kTagHardwareAddress[] = "hardwareAddress";
172 const char kTagHardwareRevision[] = "hardwareRevision";
173 const char kTagIdentity[] = "identity";
174 const char kTagIccid[] = "iccid";
175 const char kTagImei[] = "imei";
176 const char kTagImsi[] = "imsi";
177 const char kTagLanguage[] = "language";
178 const char kTagLastGoodApn[] = "lastGoodApn";
179 const char kTagLocalizedName[] = "localizedName";
180 const char kTagCellularManufacturer[] = "cellularManufacturer";
181 const char kTagMdn[] = "mdn";
182 const char kTagMeid[] = "meid";
183 const char kTagMin[] = "min";
184 const char kTagModelId[] = "modelId";
185 const char kTagName[] = "name";
186 const char kTagNameServersGoogle[] = "nameServersGoogle";
187 const char kTagNameServerType[] = "nameServerType";
188 const char kTagNetworkId[] = "networkId";
189 const char kTagNetworkName[] = "networkName";
190 const char kTagNetworkTechnology[] = "networkTechnology";
191 const char kTagOperatorCode[] = "operatorCode";
192 const char kTagOperatorName[] = "operatorName";
193 const char kTagOptions[] = "options";
194 const char kTagPassword[] = "password";
195 const char kTagPolicy[] = "policy";
196 const char kTagPreferred[] = "preferred";
197 const char kTagPrlVersion[] = "prlVersion";
198 const char kTagProviderType[] = "providerType";
199 const char kTagProviderApnList[] = "providerApnList";
200 const char kTagRecommended[] = "recommended";
201 const char kTagRecommendedValue[] = "recommendedValue";
202 const char kTagRemembered[] = "remembered";
203 const char kTagRememberedList[] = "rememberedList";
204 const char kTagRestrictedPool[] = "restrictedPool";
205 const char kTagRoamingState[] = "roamingState";
206 const char kTagServerHostname[] = "serverHostname";
207 const char kTagCarriers[] = "carriers";
208 const char kTagCurrentCarrierIndex[] = "currentCarrierIndex";
209 const char kTagServiceName[] = "serviceName";
210 const char kTagServicePath[] = "servicePath";
211 const char kTagShared[] = "shared";
212 const char kTagShowActivateButton[] = "showActivateButton";
213 const char kTagShowPreferred[] = "showPreferred";
214 const char kTagShowProxy[] = "showProxy";
215 const char kTagShowStaticIPConfig[] = "showStaticIPConfig";
216 const char kTagShowViewAccountButton[] = "showViewAccountButton";
217 const char kTagSimCardLockEnabled[] = "simCardLockEnabled";
218 const char kTagSsid[] = "ssid";
219 const char kTagStrength[] = "strength";
220 const char kTagSupportUrl[] = "supportUrl";
221 const char kTagTrue[] = "true";
222 const char kTagType[] = "type";
223 const char kTagUsername[] = "username";
224 const char kTagValue[] = "value";
225 const char kTagVpn[] = "vpn";
226 const char kTagVpnList[] = "vpnList";
227 const char kTagWifi[] = "wifi";
228 const char kTagWifiAvailable[] = "wifiAvailable";
229 const char kTagWifiEnabled[] = "wifiEnabled";
230 const char kTagWimaxAvailable[] = "wimaxAvailable";
231 const char kTagWimaxEnabled[] = "wimaxEnabled";
232 const char kTagWiredList[] = "wiredList";
233 const char kTagWirelessList[] = "wirelessList";
234 const char kTagLoggedInUserNone[] = "none";
235 const char kTagLoggedInUserRegular[] = "regular";
236 const char kTagLoggedInUserOwner[] = "owner";
237 const char kTagLoggedInUserGuest[] = "guest";
238 const char kTagLoggedInUserRetailMode[] = "retail-mode";
239 const char kTagLoggedInUserPublicAccount[] = "public-account";
240 const char kTagLoggedInUserLocallyManaged[] = "locally-managed";
241 const char kTagLoggedInUserKioskApp[] = "kiosk-app";
242
243 const int kPreferredPriority = 1;
244
245 void ShillError(const std::string& function,
246                 const std::string& error_name,
247                 scoped_ptr<base::DictionaryValue> error_data) {
248   // UpdateConnectionData may send requests for stale services; ignore
249   // these errors.
250   if (function == "UpdateConnectionData" &&
251       error_name == network_handler::kDBusFailedError)
252     return;
253   NET_LOG_ERROR("Shill Error from InternetOptionsHandler: " + error_name,
254                 function);
255 }
256
257 const NetworkState* GetNetworkState(const std::string& service_path) {
258   return NetworkHandler::Get()->network_state_handler()->
259       GetNetworkState(service_path);
260 }
261
262 void SetNetworkProperty(const std::string& service_path,
263                         const std::string& property,
264                         base::Value* value) {
265   NET_LOG_EVENT("SetNetworkProperty: " + property, service_path);
266   base::DictionaryValue properties;
267   properties.SetWithoutPathExpansion(property, value);
268   NetworkHandler::Get()->network_configuration_handler()->SetProperties(
269       service_path, properties,
270       base::Bind(&base::DoNothing),
271       base::Bind(&ShillError, "SetNetworkProperty"));
272 }
273
274 std::string LoggedInUserTypeToJSString(LoginState::LoggedInUserType type) {
275   switch (type) {
276     case LoginState::LOGGED_IN_USER_NONE:
277       return kTagLoggedInUserNone;
278     case LoginState::LOGGED_IN_USER_REGULAR:
279       return kTagLoggedInUserRegular;
280     case LoginState::LOGGED_IN_USER_OWNER:
281       return kTagLoggedInUserOwner;
282     case LoginState::LOGGED_IN_USER_GUEST:
283       return kTagLoggedInUserGuest;
284     case LoginState::LOGGED_IN_USER_RETAIL_MODE:
285       return kTagLoggedInUserRetailMode;
286     case LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT:
287       return kTagLoggedInUserPublicAccount;
288     case LoginState::LOGGED_IN_USER_LOCALLY_MANAGED:
289       return kTagLoggedInUserLocallyManaged;
290     case LoginState::LOGGED_IN_USER_KIOSK_APP:
291       return kTagLoggedInUserKioskApp;
292   }
293   NOTREACHED();
294   return std::string();
295 }
296
297 bool HasPolicyForFavorite(const FavoriteState* favorite,
298                           const PrefService* profile_prefs) {
299   return onc::HasPolicyForFavoriteNetwork(
300       profile_prefs, g_browser_process->local_state(), *favorite);
301 }
302
303 bool HasPolicyForNetwork(const NetworkState* network,
304                          const PrefService* profile_prefs) {
305   const FavoriteState* favorite =
306       NetworkHandler::Get()->network_state_handler()->GetFavoriteState(
307           network->path());
308   if (!favorite)
309     return false;
310   return HasPolicyForFavorite(favorite, profile_prefs);
311 }
312
313 void SetCommonNetworkInfo(const ManagedState* state,
314                           const gfx::ImageSkia& icon,
315                           ui::ScaleFactor icon_scale_factor,
316                           base::DictionaryValue* network_info) {
317   gfx::ImageSkiaRep image_rep =
318       icon.GetRepresentation(ui::GetImageScale(icon_scale_factor));
319   std::string icon_url =
320       icon.isNull() ? "" : webui::GetBitmapDataUrl(image_rep.sk_bitmap());
321   network_info->SetString(kNetworkInfoKeyIconURL, icon_url);
322
323   std::string name = state->name();
324   if (state->Matches(NetworkTypePattern::Ethernet())) {
325     name = internet_options_strings::NetworkDeviceTypeString(
326         shill::kTypeEthernet);
327   }
328   network_info->SetString(kNetworkInfoKeyNetworkName, name);
329   network_info->SetString(kNetworkInfoKeyNetworkType, state->type());
330   network_info->SetString(kNetworkInfoKeyServicePath, state->path());
331 }
332
333 // Builds a dictionary with network information and an icon used for the
334 // NetworkList on the settings page. Ownership of the returned pointer is
335 // transferred to the caller.
336 base::DictionaryValue* BuildNetworkDictionary(
337     const NetworkState* network,
338     ui::ScaleFactor icon_scale_factor,
339     const PrefService* profile_prefs) {
340   scoped_ptr<base::DictionaryValue> network_info(new base::DictionaryValue());
341   network_info->SetBoolean(kNetworkInfoKeyConnectable, network->connectable());
342   network_info->SetBoolean(kNetworkInfoKeyConnected,
343                            network->IsConnectedState());
344   network_info->SetBoolean(kNetworkInfoKeyConnecting,
345                            network->IsConnectingState());
346   network_info->SetBoolean(kNetworkInfoKeyPolicyManaged,
347                            HasPolicyForNetwork(network, profile_prefs));
348
349   gfx::ImageSkia icon = ash::network_icon::GetImageForNetwork(
350       network, ash::network_icon::ICON_TYPE_LIST);
351   SetCommonNetworkInfo(network, icon, icon_scale_factor, network_info.get());
352   return network_info.release();
353 }
354
355 base::DictionaryValue* BuildFavoriteDictionary(
356     const FavoriteState* favorite,
357     ui::ScaleFactor icon_scale_factor,
358     const PrefService* profile_prefs) {
359   scoped_ptr<base::DictionaryValue> network_info(new base::DictionaryValue());
360   network_info->SetBoolean(kNetworkInfoKeyConnectable, false);
361   network_info->SetBoolean(kNetworkInfoKeyConnected, false);
362   network_info->SetBoolean(kNetworkInfoKeyConnecting, false);
363   network_info->SetBoolean(kNetworkInfoKeyPolicyManaged,
364                            HasPolicyForFavorite(favorite, profile_prefs));
365
366   gfx::ImageSkia icon = ash::network_icon::GetImageForDisconnectedNetwork(
367       ash::network_icon::ICON_TYPE_LIST, favorite->type());
368   SetCommonNetworkInfo(favorite, icon, icon_scale_factor, network_info.get());
369   return network_info.release();
370 }
371
372 // Pulls IP information out of a shill service properties dictionary. If
373 // |static_ip| is true, then it fetches "StaticIP.*" properties. If not, then it
374 // fetches "SavedIP.*" properties. Caller must take ownership of returned
375 // dictionary.  If non-NULL, |ip_parameters_set| returns a count of the number
376 // of IP routing parameters that get set.
377 base::DictionaryValue* BuildIPInfoDictionary(
378     const base::DictionaryValue& shill_properties,
379     bool static_ip,
380     int* routing_parameters_set) {
381   std::string address_key;
382   std::string prefix_len_key;
383   std::string gateway_key;
384   std::string name_servers_key;
385   if (static_ip) {
386     address_key = shill::kStaticIPAddressProperty;
387     prefix_len_key = shill::kStaticIPPrefixlenProperty;
388     gateway_key = shill::kStaticIPGatewayProperty;
389     name_servers_key = shill::kStaticIPNameServersProperty;
390   } else {
391     address_key = shill::kSavedIPAddressProperty;
392     prefix_len_key = shill::kSavedIPPrefixlenProperty;
393     gateway_key = shill::kSavedIPGatewayProperty;
394     name_servers_key = shill::kSavedIPNameServersProperty;
395   }
396
397   scoped_ptr<base::DictionaryValue> ip_info_dict(new base::DictionaryValue);
398   std::string address;
399   int routing_parameters = 0;
400   if (shill_properties.GetStringWithoutPathExpansion(address_key, &address)) {
401     ip_info_dict->SetString(kIpConfigAddress, address);
402     VLOG(2) << "Found " << address_key << ": " << address;
403     routing_parameters++;
404   }
405   int prefix_len = -1;
406   if (shill_properties.GetIntegerWithoutPathExpansion(
407       prefix_len_key, &prefix_len)) {
408     ip_info_dict->SetInteger(kIpConfigPrefixLength, prefix_len);
409     std::string netmask = network_util::PrefixLengthToNetmask(prefix_len);
410     ip_info_dict->SetString(kIpConfigNetmask, netmask);
411     VLOG(2) << "Found " << prefix_len_key << ": "
412             <<  prefix_len << " (" << netmask << ")";
413     routing_parameters++;
414   }
415   std::string gateway;
416   if (shill_properties.GetStringWithoutPathExpansion(gateway_key, &gateway)) {
417     ip_info_dict->SetString(kIpConfigGateway, gateway);
418     VLOG(2) << "Found " << gateway_key << ": " << gateway;
419     routing_parameters++;
420   }
421   if (routing_parameters_set)
422     *routing_parameters_set = routing_parameters;
423
424   std::string name_servers;
425   if (shill_properties.GetStringWithoutPathExpansion(
426       name_servers_key, &name_servers)) {
427     ip_info_dict->SetString(kIpConfigNameServers, name_servers);
428     VLOG(2) << "Found " << name_servers_key << ": " << name_servers;
429   }
430
431   return ip_info_dict.release();
432 }
433
434 bool CanForgetNetworkType(const std::string& type) {
435   return type == shill::kTypeWifi ||
436          type == shill::kTypeWimax ||
437          type == shill::kTypeVPN;
438 }
439
440 bool CanAddNetworkType(const std::string& type) {
441   return type == shill::kTypeWifi ||
442          type == shill::kTypeVPN ||
443          type == shill::kTypeCellular;
444 }
445
446 // Decorate dictionary |value_dict| with policy information from |ui_data|.
447 void DecorateValueDictionary(const NetworkPropertyUIData& ui_data,
448                              const base::Value& value,
449                              base::DictionaryValue* value_dict) {
450   const base::Value* recommended_value = ui_data.default_value();
451   if (ui_data.IsManaged())
452     value_dict->SetString(kTagControlledBy, kTagPolicy);
453   else if (recommended_value && recommended_value->Equals(&value))
454     value_dict->SetString(kTagControlledBy, kTagRecommended);
455
456   if (recommended_value)
457     value_dict->Set(kTagRecommendedValue, recommended_value->DeepCopy());
458 }
459
460 // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does and
461 // store it under |key| in |settings|. Takes ownership of |value|.
462 void SetValueDictionary(base::DictionaryValue* settings,
463                         const char* key,
464                         base::Value* value,
465                         const NetworkPropertyUIData& ui_data) {
466   base::DictionaryValue* dict = new base::DictionaryValue();
467   // DictionaryValue::Set() takes ownership of |value|.
468   dict->Set(kTagValue, value);
469   settings->Set(key, dict);
470   DecorateValueDictionary(ui_data, *value, dict);
471 }
472
473 // Creates a decorated dictionary like SetValueDictionary does, but extended for
474 // the Autoconnect property, which respects additionally global network policy.
475 void SetAutoconnectValueDictionary(bool network_is_private,
476                                    ::onc::ONCSource onc_source,
477                                    bool current_autoconnect,
478                                    const NetworkPropertyUIData& ui_data,
479                                    base::DictionaryValue* settings) {
480   base::DictionaryValue* dict = new base::DictionaryValue();
481   base::Value* value = new base::FundamentalValue(current_autoconnect);
482   // DictionaryValue::Set() takes ownership of |value|.
483   dict->Set(kTagValue, value);
484   settings->Set(kTagAutoConnect, dict);
485   if (onc_source != ::onc::ONC_SOURCE_USER_POLICY &&
486       onc_source != ::onc::ONC_SOURCE_DEVICE_POLICY) {
487     // Autoconnect can be controlled by the GlobalNetworkConfiguration of the
488     // ONC policy.
489     bool only_policy_autoconnect =
490         onc::PolicyAllowsOnlyPolicyNetworksToAutoconnect(network_is_private);
491     if (only_policy_autoconnect) {
492       dict->SetString(kTagControlledBy, kTagPolicy);
493       return;
494     }
495   }
496   DecorateValueDictionary(ui_data, *value, dict);
497 }
498
499 std::string CopyStringFromDictionary(const base::DictionaryValue& source,
500                                      const std::string& src_key,
501                                      const std::string& dest_key,
502                                      base::DictionaryValue* dest) {
503   std::string string_value;
504   if (source.GetStringWithoutPathExpansion(src_key, &string_value))
505     dest->SetStringWithoutPathExpansion(dest_key, string_value);
506   return string_value;
507 }
508
509 void CopyIntegerFromDictionary(const base::DictionaryValue& source,
510                                const std::string& src_key,
511                                const std::string& dest_key,
512                                bool as_string,
513                                base::DictionaryValue* dest) {
514   int int_value;
515   if (!source.GetIntegerWithoutPathExpansion(src_key, &int_value))
516     return;
517   if (as_string) {
518     dest->SetStringWithoutPathExpansion(dest_key, base::IntToString(int_value));
519   } else {
520     dest->SetIntegerWithoutPathExpansion(dest_key, int_value);
521   }
522 }
523
524 // Fills |dictionary| with the configuration details of |vpn|. |onc| is required
525 // for augmenting the policy-managed information.
526 void PopulateVPNDetails(const NetworkState* vpn,
527                         const base::DictionaryValue& shill_properties,
528                         base::DictionaryValue* dictionary) {
529   // Name and Remembered are set in PopulateConnectionDetails().
530   // Provider properties are stored in the "Provider" dictionary.
531   const base::DictionaryValue* provider_properties = NULL;
532   if (!shill_properties.GetDictionaryWithoutPathExpansion(
533           shill::kProviderProperty, &provider_properties)) {
534     LOG(ERROR) << "No provider properties for VPN: " << vpn->path();
535     return;
536   }
537   std::string provider_type;
538   provider_properties->GetStringWithoutPathExpansion(
539       shill::kTypeProperty, &provider_type);
540   dictionary->SetString(kTagProviderType,
541                         internet_options_strings::ProviderTypeString(
542                             provider_type,
543                             *provider_properties));
544
545   std::string username;
546   if (provider_type == shill::kProviderOpenVpn) {
547     provider_properties->GetStringWithoutPathExpansion(
548         shill::kOpenVPNUserProperty, &username);
549   } else {
550     provider_properties->GetStringWithoutPathExpansion(
551         shill::kL2tpIpsecUserProperty, &username);
552   }
553   dictionary->SetString(kTagUsername, username);
554
555   ::onc::ONCSource onc_source = ::onc::ONC_SOURCE_NONE;
556   const base::DictionaryValue* onc =
557       onc::FindPolicyForActiveUser(vpn->guid(), &onc_source);
558
559   NetworkPropertyUIData hostname_ui_data;
560   hostname_ui_data.ParseOncProperty(
561       onc_source,
562       onc,
563       ::onc::network_config::VpnProperty(::onc::vpn::kHost));
564   std::string provider_host;
565   provider_properties->GetStringWithoutPathExpansion(
566       shill::kHostProperty, &provider_host);
567   SetValueDictionary(dictionary, kTagServerHostname,
568                      new base::StringValue(provider_host),
569                      hostname_ui_data);
570
571   // Disable 'Connect' for VPN unless connected to a non-VPN network.
572   const NetworkState* connected_network =
573       NetworkHandler::Get()->network_state_handler()->ConnectedNetworkByType(
574           NetworkTypePattern::NonVirtual());
575   dictionary->SetBoolean(kTagDisableConnectButton, !connected_network);
576 }
577
578 // Given a list of supported carrier's by the device, return the index of
579 // the carrier the device is currently using.
580 int FindCurrentCarrierIndex(const base::ListValue* carriers,
581                             const DeviceState* device) {
582   DCHECK(carriers);
583   DCHECK(device);
584   bool gsm = (device->technology_family() == shill::kTechnologyFamilyGsm);
585   int index = 0;
586   for (base::ListValue::const_iterator it = carriers->begin();
587        it != carriers->end(); ++it, ++index) {
588     std::string value;
589     if (!(*it)->GetAsString(&value))
590       continue;
591     // For GSM devices the device name will be empty, so simply select
592     // the Generic UMTS carrier option if present.
593     if (gsm && (value == shill::kCarrierGenericUMTS))
594       return index;
595     // For other carriers, the service name will match the carrier name.
596     if (value == device->carrier())
597       return index;
598   }
599   return -1;
600 }
601
602 void PopulateWifiDetails(const NetworkState* wifi,
603                          const base::DictionaryValue& shill_properties,
604                          base::DictionaryValue* dictionary) {
605   dictionary->SetString(kTagSsid, wifi->name());
606   dictionary->SetInteger(kTagStrength, wifi->signal_strength());
607   dictionary->SetString(kTagEncryption,
608                         internet_options_strings::EncryptionString(
609                             wifi->security(), wifi->eap_method()));
610   CopyStringFromDictionary(
611       shill_properties, shill::kWifiBSsid, kTagBssid, dictionary);
612   CopyIntegerFromDictionary(shill_properties,
613                             shill::kWifiFrequency,
614                             kTagFrequency,
615                             false,
616                             dictionary);
617 }
618
619 void PopulateWimaxDetails(const NetworkState* wimax,
620                           const base::DictionaryValue& shill_properties,
621                           base::DictionaryValue* dictionary) {
622   dictionary->SetInteger(kTagStrength, wimax->signal_strength());
623   CopyStringFromDictionary(
624       shill_properties, shill::kEapIdentityProperty, kTagIdentity, dictionary);
625 }
626
627 void CreateDictionaryFromCellularApn(const base::DictionaryValue* apn,
628                                      base::DictionaryValue* dictionary) {
629   CopyStringFromDictionary(*apn, shill::kApnProperty, kTagApn, dictionary);
630   CopyStringFromDictionary(
631       *apn, shill::kApnNetworkIdProperty, kTagNetworkId, dictionary);
632   CopyStringFromDictionary(
633       *apn, shill::kApnUsernameProperty, kTagUsername, dictionary);
634   CopyStringFromDictionary(
635       *apn, shill::kApnPasswordProperty, kTagPassword, dictionary);
636   CopyStringFromDictionary(*apn, shill::kApnNameProperty, kTagName, dictionary);
637   CopyStringFromDictionary(
638       *apn, shill::kApnLocalizedNameProperty, kTagLocalizedName, dictionary);
639   CopyStringFromDictionary(
640       *apn, shill::kApnLanguageProperty, kTagLanguage, dictionary);
641 }
642
643 void PopulateCellularDetails(const NetworkState* cellular,
644                              const base::DictionaryValue& shill_properties,
645                              base::DictionaryValue* dictionary) {
646   dictionary->SetBoolean(kTagCarrierSelectFlag,
647                          CommandLine::ForCurrentProcess()->HasSwitch(
648                              chromeos::switches::kEnableCarrierSwitching));
649   // Cellular network / connection settings.
650   dictionary->SetString(kTagNetworkTechnology, cellular->network_technology());
651   dictionary->SetString(kTagActivationState,
652                         internet_options_strings::ActivationStateString(
653                             cellular->activation_state()));
654   dictionary->SetString(kTagRoamingState,
655                         internet_options_strings::RoamingStateString(
656                             cellular->roaming()));
657   dictionary->SetString(
658       kTagRestrictedPool,
659       internet_options_strings::RestrictedStateString(
660           cellular->connection_state()));
661
662   const base::DictionaryValue* serving_operator = NULL;
663   if (shill_properties.GetDictionaryWithoutPathExpansion(
664           shill::kServingOperatorProperty, &serving_operator)) {
665     CopyStringFromDictionary(*serving_operator,
666                              shill::kOperatorNameKey,
667                              kTagOperatorName,
668                              dictionary);
669     CopyStringFromDictionary(*serving_operator,
670                              shill::kOperatorCodeKey,
671                              kTagOperatorCode,
672                              dictionary);
673   }
674
675   const base::DictionaryValue* olp = NULL;
676   if (shill_properties.GetDictionaryWithoutPathExpansion(
677           shill::kPaymentPortalProperty, &olp)) {
678     std::string url;
679     olp->GetStringWithoutPathExpansion(shill::kPaymentPortalURL, &url);
680     dictionary->SetString(kTagSupportUrl, url);
681   }
682
683   base::DictionaryValue* apn = new base::DictionaryValue;
684   const base::DictionaryValue* source_apn = NULL;
685   if (shill_properties.GetDictionaryWithoutPathExpansion(
686           shill::kCellularApnProperty, &source_apn)) {
687     CreateDictionaryFromCellularApn(source_apn, apn);
688   }
689   dictionary->Set(kTagApn, apn);
690
691   base::DictionaryValue* last_good_apn = new base::DictionaryValue;
692   if (shill_properties.GetDictionaryWithoutPathExpansion(
693           shill::kCellularLastGoodApnProperty, &source_apn)) {
694     CreateDictionaryFromCellularApn(source_apn, last_good_apn);
695   }
696   dictionary->Set(kTagLastGoodApn, last_good_apn);
697
698   // These default to empty and are only set if device != NULL.
699   std::string carrier_id;
700   std::string mdn;
701
702   // Device settings.
703   const DeviceState* device =
704       NetworkHandler::Get()->network_state_handler()->GetDeviceState(
705           cellular->device_path());
706   if (device) {
707     // TODO(stevenjb): Add NetworkDeviceHandler::GetProperties() and use that
708     // to retrieve the complete dictionary of device properties, instead of
709     // caching them (will be done for the new UI).
710     const base::DictionaryValue& device_properties = device->properties();
711     const NetworkPropertyUIData cellular_property_ui_data(
712         cellular->ui_data().onc_source());
713     CopyStringFromDictionary(device_properties,
714                              shill::kManufacturerProperty,
715                              kTagCellularManufacturer,
716                              dictionary);
717     CopyStringFromDictionary(
718         device_properties, shill::kModelIDProperty, kTagModelId, dictionary);
719     CopyStringFromDictionary(device_properties,
720                              shill::kFirmwareRevisionProperty,
721                              kTagFirmwareRevision,
722                              dictionary);
723     CopyStringFromDictionary(device_properties,
724                              shill::kHardwareRevisionProperty,
725                              kTagHardwareRevision,
726                              dictionary);
727     CopyIntegerFromDictionary(device_properties,
728                               shill::kPRLVersionProperty,
729                               kTagPrlVersion,
730                               true,
731                               dictionary);
732     CopyStringFromDictionary(
733         device_properties, shill::kMeidProperty, kTagMeid, dictionary);
734     CopyStringFromDictionary(
735         device_properties, shill::kIccidProperty, kTagIccid, dictionary);
736     CopyStringFromDictionary(
737         device_properties, shill::kImeiProperty, kTagImei, dictionary);
738     mdn = CopyStringFromDictionary(
739         device_properties, shill::kMdnProperty, kTagMdn, dictionary);
740     CopyStringFromDictionary(
741         device_properties, shill::kImsiProperty, kTagImsi, dictionary);
742     CopyStringFromDictionary(
743         device_properties, shill::kEsnProperty, kTagEsn, dictionary);
744     CopyStringFromDictionary(
745         device_properties, shill::kMinProperty, kTagMin, dictionary);
746     std::string family;
747     device_properties.GetStringWithoutPathExpansion(
748         shill::kTechnologyFamilyProperty, &family);
749     dictionary->SetBoolean(kTagGsm, family == shill::kNetworkTechnologyGsm);
750
751     SetValueDictionary(dictionary,
752                        kTagSimCardLockEnabled,
753                        new base::FundamentalValue(device->sim_lock_enabled()),
754                        cellular_property_ui_data);
755
756     carrier_id = device->home_provider_id();
757
758     MobileConfig* config = MobileConfig::GetInstance();
759     if (config->IsReady()) {
760       const MobileConfig::Carrier* carrier = config->GetCarrier(carrier_id);
761       if (carrier && !carrier->top_up_url().empty())
762         dictionary->SetString(kTagCarrierUrl, carrier->top_up_url());
763     }
764
765     base::ListValue* apn_list_value = new base::ListValue();
766     const base::ListValue* apn_list;
767     if (device_properties.GetListWithoutPathExpansion(
768             shill::kCellularApnListProperty, &apn_list)) {
769       for (base::ListValue::const_iterator iter = apn_list->begin();
770            iter != apn_list->end();
771            ++iter) {
772         const base::DictionaryValue* dict;
773         if ((*iter)->GetAsDictionary(&dict)) {
774           base::DictionaryValue* apn = new base::DictionaryValue;
775           CreateDictionaryFromCellularApn(dict, apn);
776           apn_list_value->Append(apn);
777         }
778       }
779     }
780     SetValueDictionary(dictionary,
781                        kTagProviderApnList,
782                        apn_list_value,
783                        cellular_property_ui_data);
784     if (CommandLine::ForCurrentProcess()->HasSwitch(
785             chromeos::switches::kEnableCarrierSwitching)) {
786       const base::ListValue* supported_carriers;
787       if (device_properties.GetListWithoutPathExpansion(
788               shill::kSupportedCarriersProperty, &supported_carriers)) {
789         dictionary->Set(kTagCarriers, supported_carriers->DeepCopy());
790         dictionary->SetInteger(
791             kTagCurrentCarrierIndex,
792             FindCurrentCarrierIndex(supported_carriers, device));
793       } else {
794         // In case of any error, set the current carrier tag to -1 indicating
795         // to the JS code to fallback to a single carrier.
796         dictionary->SetInteger(kTagCurrentCarrierIndex, -1);
797       }
798     }
799   }
800
801   // Set Cellular Buttons Visibility
802   dictionary->SetBoolean(
803       kTagDisableConnectButton,
804       cellular->activation_state() == shill::kActivationStateActivating ||
805           cellular->IsConnectingState());
806
807   // Don't show any account management related buttons if the activation
808   // state is unknown or no payment portal URL is available.
809   std::string support_url;
810   if (cellular->activation_state() == shill::kActivationStateUnknown ||
811       !dictionary->GetString(kTagSupportUrl, &support_url) ||
812       support_url.empty()) {
813     VLOG(2) << "No support URL is available. Don't display buttons.";
814     return;
815   }
816
817   if (cellular->activation_state() != shill::kActivationStateActivating &&
818       cellular->activation_state() != shill::kActivationStateActivated) {
819     dictionary->SetBoolean(kTagShowActivateButton, true);
820   } else {
821     bool may_show_portal_button = false;
822
823     // If an online payment URL was provided by shill, then this means that the
824     // "View Account" button should be shown for the current carrier.
825     if (olp) {
826       std::string url;
827       olp->GetStringWithoutPathExpansion(shill::kPaymentPortalURL, &url);
828       may_show_portal_button = !url.empty();
829     }
830     // If no online payment URL was provided by shill, fall back to
831     // MobileConfig to determine if the "View Account" should be shown.
832     if (!may_show_portal_button && MobileConfig::GetInstance()->IsReady()) {
833       const MobileConfig::Carrier* carrier =
834           MobileConfig::GetInstance()->GetCarrier(carrier_id);
835       may_show_portal_button = carrier && carrier->show_portal_button();
836     }
837     if (may_show_portal_button) {
838       // The button should be shown for a LTE network even when the LTE network
839       // is not connected, but CrOS is online. This is done to enable users to
840       // update their plan even if they are out of credits.
841       // The button should not be shown when the device's mdn is not set,
842       // because the network's proper portal url cannot be generated without it
843       const NetworkState* default_network =
844           NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
845       const std::string& technology = cellular->network_technology();
846       bool force_show_view_account_button =
847           (technology == shill::kNetworkTechnologyLte ||
848            technology == shill::kNetworkTechnologyLteAdvanced) &&
849           default_network && !mdn.empty();
850
851       // The button will trigger ShowMorePlanInfoCallback() which will open
852       // carrier specific portal.
853       if (cellular->IsConnectedState() || force_show_view_account_button)
854         dictionary->SetBoolean(kTagShowViewAccountButton, true);
855     }
856   }
857 }
858
859 void PopulateConnectionDetails(const NetworkState* network,
860                                const base::DictionaryValue& shill_properties,
861                                base::DictionaryValue* dictionary) {
862   dictionary->SetString(kNetworkInfoKeyServicePath, network->path());
863   dictionary->SetString(kTagServiceName, network->name());
864   dictionary->SetBoolean(kTagConnecting, network->IsConnectingState());
865   dictionary->SetBoolean(kTagConnected, network->IsConnectedState());
866   dictionary->SetString(kTagConnectionState,
867                         internet_options_strings::ConnectionStateString(
868                             network->connection_state()));
869   dictionary->SetString(kTagNetworkName, network->name());
870   dictionary->SetString(
871       kTagErrorState,
872       ash::network_connect::ErrorString(network->error(), network->path()));
873
874   dictionary->SetBoolean(kTagRemembered, !network->profile_path().empty());
875   bool shared = !network->IsPrivate();
876   dictionary->SetBoolean(kTagShared, shared);
877
878   const std::string& type = network->type();
879   const NetworkState* connected_network =
880       NetworkHandler::Get()->network_state_handler()->ConnectedNetworkByType(
881           NetworkTypePattern::Primitive(type));
882
883   dictionary->SetBoolean(kTagDeviceConnected, connected_network != NULL);
884
885   if (type == shill::kTypeWifi)
886     PopulateWifiDetails(network, shill_properties, dictionary);
887   else if (type == shill::kTypeWimax)
888     PopulateWimaxDetails(network, shill_properties, dictionary);
889   else if (type == shill::kTypeCellular)
890     PopulateCellularDetails(network, shill_properties, dictionary);
891   else if (type == shill::kTypeVPN)
892     PopulateVPNDetails(network, shill_properties, dictionary);
893 }
894
895 // Helper methods for SetIPConfigProperties
896 bool AppendPropertyKeyIfPresent(const std::string& key,
897                                 const base::DictionaryValue& old_properties,
898                                 std::vector<std::string>* property_keys) {
899   if (old_properties.HasKey(key)) {
900     property_keys->push_back(key);
901     return true;
902   }
903   return false;
904 }
905
906 bool AddStringPropertyIfChanged(const std::string& key,
907                                 const std::string& new_value,
908                                 const base::DictionaryValue& old_properties,
909                                 base::DictionaryValue* new_properties) {
910   std::string old_value;
911   if (!old_properties.GetStringWithoutPathExpansion(key, &old_value) ||
912       new_value != old_value) {
913     new_properties->SetStringWithoutPathExpansion(key, new_value);
914     return true;
915   }
916   return false;
917 }
918
919 bool AddIntegerPropertyIfChanged(const std::string& key,
920                                  int new_value,
921                                  const base::DictionaryValue& old_properties,
922                                  base::DictionaryValue* new_properties) {
923   int old_value;
924   if (!old_properties.GetIntegerWithoutPathExpansion(key, &old_value) ||
925       new_value != old_value) {
926     new_properties->SetIntegerWithoutPathExpansion(key, new_value);
927     return true;
928   }
929   return false;
930 }
931
932 void RequestReconnect(const std::string& service_path,
933                       gfx::NativeWindow owning_window) {
934   NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
935       service_path,
936       base::Bind(&ash::network_connect::ConnectToNetwork,
937                  service_path, owning_window),
938       base::Bind(&ShillError, "RequestReconnect"));
939 }
940
941 }  // namespace
942
943 InternetOptionsHandler::InternetOptionsHandler()
944     : weak_factory_(this) {
945   registrar_.Add(this, chrome::NOTIFICATION_REQUIRE_PIN_SETTING_CHANGE_ENDED,
946                  content::NotificationService::AllSources());
947   registrar_.Add(this, chrome::NOTIFICATION_ENTER_PIN_ENDED,
948                  content::NotificationService::AllSources());
949   NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);
950   LoginState::Get()->AddObserver(this);
951 }
952
953 InternetOptionsHandler::~InternetOptionsHandler() {
954   if (NetworkHandler::IsInitialized()) {
955     NetworkHandler::Get()->network_state_handler()->RemoveObserver(
956         this, FROM_HERE);
957   }
958   if (LoginState::Get()->IsInitialized())
959     LoginState::Get()->RemoveObserver(this);
960 }
961
962 void InternetOptionsHandler::GetLocalizedValues(
963     base::DictionaryValue* localized_strings) {
964   DCHECK(localized_strings);
965   internet_options_strings::RegisterLocalizedStrings(localized_strings);
966
967   std::string owner;
968   chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
969   localized_strings->SetString("ownerUserId", base::UTF8ToUTF16(owner));
970
971   base::DictionaryValue* network_dictionary = new base::DictionaryValue;
972   FillNetworkInfo(network_dictionary);
973   localized_strings->Set("networkData", network_dictionary);
974 }
975
976 void InternetOptionsHandler::InitializePage() {
977   base::DictionaryValue dictionary;
978   dictionary.SetString(kTagCellular,
979       GetIconDataUrl(IDR_AURA_UBER_TRAY_NETWORK_BARS_DARK));
980   dictionary.SetString(kTagWifi,
981       GetIconDataUrl(IDR_AURA_UBER_TRAY_NETWORK_ARCS_DARK));
982   dictionary.SetString(kTagVpn,
983       GetIconDataUrl(IDR_AURA_UBER_TRAY_NETWORK_VPN));
984   web_ui()->CallJavascriptFunction(kSetDefaultNetworkIconsFunction,
985                                    dictionary);
986   NetworkHandler::Get()->network_state_handler()->RequestScan();
987   RefreshNetworkData();
988   UpdateLoggedInUserType();
989 }
990
991 void InternetOptionsHandler::RegisterMessages() {
992   // Setup handlers specific to this panel.
993   web_ui()->RegisterMessageCallback(kNetworkCommandMessage,
994       base::Bind(&InternetOptionsHandler::NetworkCommandCallback,
995                  base::Unretained(this)));
996   web_ui()->RegisterMessageCallback(kRefreshNetworksMessage,
997       base::Bind(&InternetOptionsHandler::RefreshNetworksCallback,
998                  base::Unretained(this)));
999   web_ui()->RegisterMessageCallback(kSetPreferNetworkMessage,
1000       base::Bind(&InternetOptionsHandler::SetPreferNetworkCallback,
1001                  base::Unretained(this)));
1002   web_ui()->RegisterMessageCallback(kSetAutoConnectMessage,
1003       base::Bind(&InternetOptionsHandler::SetAutoConnectCallback,
1004                  base::Unretained(this)));
1005   web_ui()->RegisterMessageCallback(kSetIPConfigMessage,
1006       base::Bind(&InternetOptionsHandler::SetIPConfigCallback,
1007                  base::Unretained(this)));
1008   web_ui()->RegisterMessageCallback(kEnableWifiMessage,
1009       base::Bind(&InternetOptionsHandler::EnableWifiCallback,
1010                  base::Unretained(this)));
1011   web_ui()->RegisterMessageCallback(kDisableWifiMessage,
1012       base::Bind(&InternetOptionsHandler::DisableWifiCallback,
1013                  base::Unretained(this)));
1014   web_ui()->RegisterMessageCallback(kEnableCellularMessage,
1015       base::Bind(&InternetOptionsHandler::EnableCellularCallback,
1016                  base::Unretained(this)));
1017   web_ui()->RegisterMessageCallback(kDisableCellularMessage,
1018       base::Bind(&InternetOptionsHandler::DisableCellularCallback,
1019                  base::Unretained(this)));
1020   web_ui()->RegisterMessageCallback(kEnableWimaxMessage,
1021       base::Bind(&InternetOptionsHandler::EnableWimaxCallback,
1022                  base::Unretained(this)));
1023   web_ui()->RegisterMessageCallback(kDisableWimaxMessage,
1024       base::Bind(&InternetOptionsHandler::DisableWimaxCallback,
1025                  base::Unretained(this)));
1026   web_ui()->RegisterMessageCallback(kBuyDataPlanMessage,
1027       base::Bind(&InternetOptionsHandler::BuyDataPlanCallback,
1028                  base::Unretained(this)));
1029   web_ui()->RegisterMessageCallback(kShowMorePlanInfoMessage,
1030       base::Bind(&InternetOptionsHandler::ShowMorePlanInfoCallback,
1031                  base::Unretained(this)));
1032   web_ui()->RegisterMessageCallback(kSetApnMessage,
1033       base::Bind(&InternetOptionsHandler::SetApnCallback,
1034                  base::Unretained(this)));
1035   web_ui()->RegisterMessageCallback(kSetCarrierMessage,
1036       base::Bind(&InternetOptionsHandler::SetCarrierCallback,
1037                  base::Unretained(this)));
1038   web_ui()->RegisterMessageCallback(kSetSimCardLockMessage,
1039       base::Bind(&InternetOptionsHandler::SetSimCardLockCallback,
1040                  base::Unretained(this)));
1041   web_ui()->RegisterMessageCallback(kChangePinMessage,
1042       base::Bind(&InternetOptionsHandler::ChangePinCallback,
1043                  base::Unretained(this)));
1044   web_ui()->RegisterMessageCallback(kSetServerHostname,
1045       base::Bind(&InternetOptionsHandler::SetServerHostnameCallback,
1046                  base::Unretained(this)));
1047 }
1048
1049 void InternetOptionsHandler::EnableWifiCallback(const base::ListValue* args) {
1050   content::RecordAction(base::UserMetricsAction("Options_NetworkWifiToggle"));
1051   NetworkHandler::Get()->network_state_handler()->SetTechnologyEnabled(
1052       NetworkTypePattern::WiFi(), true,
1053       base::Bind(&ShillError, "EnableWifiCallback"));
1054 }
1055
1056 void InternetOptionsHandler::DisableWifiCallback(const base::ListValue* args) {
1057   content::RecordAction(base::UserMetricsAction("Options_NetworkWifiToggle"));
1058   NetworkHandler::Get()->network_state_handler()->SetTechnologyEnabled(
1059       NetworkTypePattern::WiFi(), false,
1060       base::Bind(&ShillError, "DisableWifiCallback"));
1061 }
1062
1063 void InternetOptionsHandler::EnableCellularCallback(
1064     const base::ListValue* args) {
1065   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
1066   const DeviceState* device =
1067       handler->GetDeviceStateByType(NetworkTypePattern::Cellular());
1068   if (!device) {
1069     LOG(ERROR) << "Mobile device not found.";
1070     return;
1071   }
1072   if (!device->sim_lock_type().empty()) {
1073     SimDialogDelegate::ShowDialog(GetNativeWindow(),
1074                                   SimDialogDelegate::SIM_DIALOG_UNLOCK);
1075     return;
1076   }
1077   if (!handler->IsTechnologyEnabled(NetworkTypePattern::Cellular())) {
1078     handler->SetTechnologyEnabled(
1079         NetworkTypePattern::Cellular(), true,
1080         base::Bind(&ShillError, "EnableCellularCallback"));
1081     return;
1082   }
1083   if (device->IsSimAbsent()) {
1084     mobile_config_ui::DisplayConfigDialog();
1085     return;
1086   }
1087   LOG(ERROR) << "EnableCellularCallback called for enabled mobile device";
1088 }
1089
1090 void InternetOptionsHandler::DisableCellularCallback(
1091     const base::ListValue* args) {
1092   NetworkHandler::Get()->network_state_handler()->SetTechnologyEnabled(
1093       NetworkTypePattern::Mobile(), false,
1094       base::Bind(&ShillError, "DisableCellularCallback"));
1095 }
1096
1097 void InternetOptionsHandler::EnableWimaxCallback(const base::ListValue* args) {
1098   NetworkHandler::Get()->network_state_handler()->SetTechnologyEnabled(
1099       NetworkTypePattern::Wimax(), true,
1100       base::Bind(&ShillError, "EnableWimaxCallback"));
1101 }
1102
1103 void InternetOptionsHandler::DisableWimaxCallback(const base::ListValue* args) {
1104   NetworkHandler::Get()->network_state_handler()->SetTechnologyEnabled(
1105       NetworkTypePattern::Wimax(), false,
1106       base::Bind(&ShillError, "DisableWimaxCallback"));
1107 }
1108
1109 void InternetOptionsHandler::ShowMorePlanInfoCallback(
1110     const base::ListValue* args) {
1111   if (!web_ui())
1112     return;
1113   std::string service_path;
1114   if (args->GetSize() != 1 || !args->GetString(0, &service_path)) {
1115     NOTREACHED();
1116     return;
1117   }
1118   ash::network_connect::ShowMobileSetup(service_path);
1119 }
1120
1121 void InternetOptionsHandler::BuyDataPlanCallback(const base::ListValue* args) {
1122   if (!web_ui())
1123     return;
1124   std::string service_path;
1125   if (args->GetSize() != 1 || !args->GetString(0, &service_path)) {
1126     NOTREACHED();
1127     return;
1128   }
1129   ash::network_connect::ShowMobileSetup(service_path);
1130 }
1131
1132 void InternetOptionsHandler::SetApnCallback(const base::ListValue* args) {
1133   std::string service_path;
1134   if (!args->GetString(0, &service_path)) {
1135     NOTREACHED();
1136     return;
1137   }
1138   NetworkHandler::Get()->network_configuration_handler()->GetProperties(
1139       service_path,
1140       base::Bind(&InternetOptionsHandler::SetApnProperties,
1141                  weak_factory_.GetWeakPtr(), base::Owned(args->DeepCopy())),
1142       base::Bind(&ShillError, "SetApnCallback"));
1143 }
1144
1145 void InternetOptionsHandler::SetApnProperties(
1146     const base::ListValue* args,
1147     const std::string& service_path,
1148     const base::DictionaryValue& shill_properties) {
1149   std::string apn, username, password;
1150   if (!args->GetString(1, &apn) ||
1151       !args->GetString(2, &username) ||
1152       !args->GetString(3, &password)) {
1153     NOTREACHED();
1154     return;
1155   }
1156   NET_LOG_EVENT("SetApnCallback", service_path);
1157
1158   if (apn.empty()) {
1159     std::vector<std::string> properties_to_clear;
1160     properties_to_clear.push_back(shill::kCellularApnProperty);
1161     NetworkHandler::Get()->network_configuration_handler()->ClearProperties(
1162       service_path, properties_to_clear,
1163       base::Bind(&base::DoNothing),
1164       base::Bind(&ShillError, "ClearCellularApnProperties"));
1165     return;
1166   }
1167
1168   const base::DictionaryValue* shill_apn_dict = NULL;
1169   std::string network_id;
1170   if (shill_properties.GetDictionaryWithoutPathExpansion(
1171           shill::kCellularApnProperty, &shill_apn_dict)) {
1172     shill_apn_dict->GetStringWithoutPathExpansion(
1173         shill::kApnNetworkIdProperty, &network_id);
1174   }
1175   base::DictionaryValue properties;
1176   base::DictionaryValue* apn_dict = new base::DictionaryValue;
1177   apn_dict->SetStringWithoutPathExpansion(shill::kApnProperty, apn);
1178   apn_dict->SetStringWithoutPathExpansion(shill::kApnNetworkIdProperty,
1179                                           network_id);
1180   apn_dict->SetStringWithoutPathExpansion(shill::kApnUsernameProperty,
1181                                           username);
1182   apn_dict->SetStringWithoutPathExpansion(shill::kApnPasswordProperty,
1183                                           password);
1184   properties.SetWithoutPathExpansion(shill::kCellularApnProperty, apn_dict);
1185   NetworkHandler::Get()->network_configuration_handler()->SetProperties(
1186       service_path, properties,
1187       base::Bind(&base::DoNothing),
1188       base::Bind(&ShillError, "SetApnProperties"));
1189 }
1190
1191 void InternetOptionsHandler::CarrierStatusCallback() {
1192   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
1193   const DeviceState* device =
1194       handler->GetDeviceStateByType(NetworkTypePattern::Cellular());
1195   if (device && (device->carrier() == shill::kCarrierSprint)) {
1196     const NetworkState* network =
1197         handler->FirstNetworkByType(NetworkTypePattern::Cellular());
1198     if (network) {
1199       ash::network_connect::ActivateCellular(network->path());
1200       UpdateConnectionData(network->path());
1201     }
1202   }
1203   UpdateCarrier();
1204 }
1205
1206 void InternetOptionsHandler::SetCarrierCallback(const base::ListValue* args) {
1207   std::string service_path;
1208   std::string carrier;
1209   if (args->GetSize() != 2 ||
1210       !args->GetString(0, &service_path) ||
1211       !args->GetString(1, &carrier)) {
1212     NOTREACHED();
1213     return;
1214   }
1215   const DeviceState* device = NetworkHandler::Get()->network_state_handler()->
1216       GetDeviceStateByType(NetworkTypePattern::Cellular());
1217   if (!device) {
1218     LOG(WARNING) << "SetCarrierCallback with no cellular device.";
1219     return;
1220   }
1221   NetworkHandler::Get()->network_device_handler()->SetCarrier(
1222       device->path(),
1223       carrier,
1224       base::Bind(&InternetOptionsHandler::CarrierStatusCallback,
1225                  weak_factory_.GetWeakPtr()),
1226       base::Bind(&ShillError, "SetCarrierCallback"));
1227 }
1228
1229 void InternetOptionsHandler::SetSimCardLockCallback(
1230     const base::ListValue* args) {
1231   bool require_pin_new_value;
1232   if (!args->GetBoolean(0, &require_pin_new_value)) {
1233     NOTREACHED();
1234     return;
1235   }
1236   // 1. Bring up SIM unlock dialog, pass new RequirePin setting in URL.
1237   // 2. Dialog will ask for current PIN in any case.
1238   // 3. If card is locked it will first call PIN unlock operation
1239   // 4. Then it will call Set RequirePin, passing the same PIN.
1240   // 5. We'll get notified by REQUIRE_PIN_SETTING_CHANGE_ENDED notification.
1241   SimDialogDelegate::SimDialogMode mode;
1242   if (require_pin_new_value)
1243     mode = SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON;
1244   else
1245     mode = SimDialogDelegate::SIM_DIALOG_SET_LOCK_OFF;
1246   SimDialogDelegate::ShowDialog(GetNativeWindow(), mode);
1247 }
1248
1249 void InternetOptionsHandler::ChangePinCallback(const base::ListValue* args) {
1250   SimDialogDelegate::ShowDialog(GetNativeWindow(),
1251                                 SimDialogDelegate::SIM_DIALOG_CHANGE_PIN);
1252 }
1253
1254 void InternetOptionsHandler::RefreshNetworksCallback(
1255     const base::ListValue* args) {
1256   NetworkHandler::Get()->network_state_handler()->RequestScan();
1257 }
1258
1259 std::string InternetOptionsHandler::GetIconDataUrl(int resource_id) const {
1260   gfx::ImageSkia* icon =
1261       ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
1262   gfx::ImageSkiaRep image_rep = icon->GetRepresentation(
1263       ui::GetImageScale(web_ui()->GetDeviceScaleFactor()));
1264   return webui::GetBitmapDataUrl(image_rep.sk_bitmap());
1265 }
1266
1267 void InternetOptionsHandler::RefreshNetworkData() {
1268   base::DictionaryValue dictionary;
1269   FillNetworkInfo(&dictionary);
1270   web_ui()->CallJavascriptFunction(
1271       kRefreshNetworkDataFunction, dictionary);
1272 }
1273
1274 void InternetOptionsHandler::UpdateConnectionData(
1275     const std::string& service_path) {
1276   NetworkHandler::Get()->network_configuration_handler()->GetProperties(
1277       service_path,
1278       base::Bind(&InternetOptionsHandler::UpdateConnectionDataCallback,
1279                  weak_factory_.GetWeakPtr()),
1280       base::Bind(&ShillError, "UpdateConnectionData"));
1281 }
1282
1283 void InternetOptionsHandler::UpdateConnectionDataCallback(
1284     const std::string& service_path,
1285     const base::DictionaryValue& shill_properties) {
1286   const NetworkState* network = GetNetworkState(service_path);
1287   if (!network)
1288     return;
1289   base::DictionaryValue dictionary;
1290   PopulateConnectionDetails(network, shill_properties, &dictionary);
1291   web_ui()->CallJavascriptFunction(kUpdateConnectionDataFunction, dictionary);
1292 }
1293
1294 void InternetOptionsHandler::UpdateCarrier() {
1295   web_ui()->CallJavascriptFunction(kUpdateCarrierFunction);
1296 }
1297
1298 void InternetOptionsHandler::DeviceListChanged() {
1299   if (!web_ui())
1300     return;
1301   RefreshNetworkData();
1302 }
1303
1304 void InternetOptionsHandler::NetworkListChanged() {
1305   if (!web_ui())
1306     return;
1307   RefreshNetworkData();
1308 }
1309
1310 void InternetOptionsHandler::NetworkConnectionStateChanged(
1311     const NetworkState* network) {
1312   if (!web_ui())
1313     return;
1314   // Update the connection data for the detailed view when the connection state
1315   // of any network changes.
1316   if (!details_path_.empty())
1317     UpdateConnectionData(details_path_);
1318 }
1319
1320 void InternetOptionsHandler::NetworkPropertiesUpdated(
1321     const NetworkState* network) {
1322   if (!web_ui())
1323     return;
1324   RefreshNetworkData();
1325   UpdateConnectionData(network->path());
1326 }
1327
1328 void InternetOptionsHandler::LoggedInStateChanged() {
1329   UpdateLoggedInUserType();
1330 }
1331
1332 void InternetOptionsHandler::UpdateLoggedInUserType() {
1333   if (!web_ui())
1334     return;
1335   base::StringValue login_type(
1336       LoggedInUserTypeToJSString(LoginState::Get()->GetLoggedInUserType()));
1337   web_ui()->CallJavascriptFunction(kUpdateLoggedInUserTypeFunction, login_type);
1338 }
1339
1340 void InternetOptionsHandler::Observe(
1341     int type,
1342     const content::NotificationSource& source,
1343     const content::NotificationDetails& details) {
1344   if (type == chrome::NOTIFICATION_REQUIRE_PIN_SETTING_CHANGE_ENDED) {
1345     base::FundamentalValue require_pin(*content::Details<bool>(details).ptr());
1346     web_ui()->CallJavascriptFunction(
1347         kUpdateSecurityTabFunction, require_pin);
1348   } else if (type == chrome::NOTIFICATION_ENTER_PIN_ENDED) {
1349     // We make an assumption (which is valid for now) that the SIM
1350     // unlock dialog is put up only when the user is trying to enable
1351     // mobile data.
1352     bool cancelled = *content::Details<bool>(details).ptr();
1353     if (cancelled)
1354       RefreshNetworkData();
1355     // The case in which the correct PIN was entered and the SIM is
1356     // now unlocked is handled in NetworkMenuButton.
1357   }
1358 }
1359
1360 void InternetOptionsHandler::SetServerHostnameCallback(
1361     const base::ListValue* args) {
1362   std::string service_path, server_hostname;
1363   if (args->GetSize() < 2 ||
1364       !args->GetString(0, &service_path) ||
1365       !args->GetString(1, &server_hostname)) {
1366     NOTREACHED();
1367     return;
1368   }
1369   SetNetworkProperty(service_path, shill::kProviderHostProperty,
1370                      base::Value::CreateStringValue(server_hostname));
1371 }
1372
1373 void InternetOptionsHandler::SetPreferNetworkCallback(
1374     const base::ListValue* args) {
1375   std::string service_path, prefer_network_str;
1376   if (args->GetSize() < 2 ||
1377       !args->GetString(0, &service_path) ||
1378       !args->GetString(1, &prefer_network_str)) {
1379     NOTREACHED();
1380     return;
1381   }
1382   content::RecordAction(base::UserMetricsAction("Options_NetworkSetPrefer"));
1383   int priority = (prefer_network_str == kTagTrue) ? kPreferredPriority : 0;
1384   SetNetworkProperty(service_path, shill::kPriorityProperty,
1385                      base::Value::CreateIntegerValue(priority));
1386 }
1387
1388 void InternetOptionsHandler::SetAutoConnectCallback(
1389     const base::ListValue* args) {
1390   std::string service_path, auto_connect_str;
1391   if (args->GetSize() < 2 ||
1392       !args->GetString(0, &service_path) ||
1393       !args->GetString(1, &auto_connect_str)) {
1394     NOTREACHED();
1395     return;
1396   }
1397   content::RecordAction(base::UserMetricsAction("Options_NetworkAutoConnect"));
1398   bool auto_connect = auto_connect_str == kTagTrue;
1399   SetNetworkProperty(service_path, shill::kAutoConnectProperty,
1400                      base::Value::CreateBooleanValue(auto_connect));
1401 }
1402
1403 void InternetOptionsHandler::SetIPConfigCallback(const base::ListValue* args) {
1404   std::string service_path;
1405   if (!args->GetString(0, &service_path)) {
1406     NOTREACHED();
1407     return;
1408   }
1409   NetworkHandler::Get()->network_configuration_handler()->GetProperties(
1410       service_path,
1411       base::Bind(&InternetOptionsHandler::SetIPConfigProperties,
1412                  weak_factory_.GetWeakPtr(), base::Owned(args->DeepCopy())),
1413       base::Bind(&ShillError, "SetIPConfigCallback"));
1414 }
1415
1416 void InternetOptionsHandler::SetIPConfigProperties(
1417     const base::ListValue* args,
1418     const std::string& service_path,
1419     const base::DictionaryValue& shill_properties) {
1420   std::string address, netmask, gateway, name_server_type, name_servers;
1421   bool dhcp_for_ip;
1422   if (!args->GetBoolean(1, &dhcp_for_ip) ||
1423       !args->GetString(2, &address) ||
1424       !args->GetString(3, &netmask) ||
1425       !args->GetString(4, &gateway) ||
1426       !args->GetString(5, &name_server_type) ||
1427       !args->GetString(6, &name_servers)) {
1428     NOTREACHED();
1429     return;
1430   }
1431   NET_LOG_USER("SetIPConfigProperties", service_path);
1432
1433   bool request_reconnect = false;
1434   std::vector<std::string> properties_to_clear;
1435   base::DictionaryValue properties_to_set;
1436
1437   if (dhcp_for_ip) {
1438     request_reconnect |= AppendPropertyKeyIfPresent(
1439         shill::kStaticIPAddressProperty,
1440         shill_properties, &properties_to_clear);
1441     request_reconnect |= AppendPropertyKeyIfPresent(
1442         shill::kStaticIPPrefixlenProperty,
1443         shill_properties, &properties_to_clear);
1444     request_reconnect |= AppendPropertyKeyIfPresent(
1445         shill::kStaticIPGatewayProperty,
1446         shill_properties, &properties_to_clear);
1447   } else {
1448     request_reconnect |= AddStringPropertyIfChanged(
1449         shill::kStaticIPAddressProperty,
1450         address, shill_properties, &properties_to_set);
1451     int prefixlen = network_util::NetmaskToPrefixLength(netmask);
1452     if (prefixlen < 0) {
1453       LOG(ERROR) << "Invalid prefix length for: " << service_path
1454                  << " with netmask " << netmask;
1455       prefixlen = 0;
1456     }
1457     request_reconnect |= AddIntegerPropertyIfChanged(
1458         shill::kStaticIPPrefixlenProperty,
1459         prefixlen, shill_properties, &properties_to_set);
1460     request_reconnect |= AddStringPropertyIfChanged(
1461         shill::kStaticIPGatewayProperty,
1462         gateway, shill_properties, &properties_to_set);
1463   }
1464
1465   if (name_server_type == kNameServerTypeAutomatic) {
1466     AppendPropertyKeyIfPresent(shill::kStaticIPNameServersProperty,
1467                                shill_properties, &properties_to_clear);
1468   } else {
1469     if (name_server_type == kNameServerTypeGoogle)
1470       name_servers = kGoogleNameServers;
1471     AddStringPropertyIfChanged(
1472         shill::kStaticIPNameServersProperty,
1473         name_servers, shill_properties, &properties_to_set);
1474   }
1475
1476   if (!properties_to_clear.empty()) {
1477     NetworkHandler::Get()->network_configuration_handler()->ClearProperties(
1478       service_path, properties_to_clear,
1479       base::Bind(&base::DoNothing),
1480       base::Bind(&ShillError, "ClearIPConfigProperties"));
1481   }
1482   if (!properties_to_set.empty()) {
1483     NetworkHandler::Get()->network_configuration_handler()->SetProperties(
1484         service_path, properties_to_set,
1485         base::Bind(&base::DoNothing),
1486         base::Bind(&ShillError, "SetIPConfigProperties"));
1487   }
1488   std::string device_path;
1489   shill_properties.GetStringWithoutPathExpansion(
1490       shill::kDeviceProperty, &device_path);
1491   if (!device_path.empty()) {
1492     base::Closure callback = base::Bind(&base::DoNothing);
1493     // If auto config or a static IP property changed, we need to reconnect
1494     // to the network.
1495     if (request_reconnect)
1496       callback = base::Bind(&RequestReconnect, service_path, GetNativeWindow());
1497     NetworkHandler::Get()->network_device_handler()->RequestRefreshIPConfigs(
1498         device_path,
1499         callback,
1500         base::Bind(&ShillError, "RequestRefreshIPConfigs"));
1501   }
1502 }
1503
1504 void InternetOptionsHandler::PopulateDictionaryDetailsCallback(
1505     const std::string& service_path,
1506     const base::DictionaryValue& shill_properties) {
1507   const NetworkState* network = GetNetworkState(service_path);
1508   if (!network) {
1509     LOG(ERROR) << "Network properties not found: " << service_path;
1510     return;
1511   }
1512
1513   details_path_ = service_path;
1514
1515   ::onc::ONCSource onc_source = ::onc::ONC_SOURCE_NONE;
1516   const base::DictionaryValue* onc =
1517       onc::FindPolicyForActiveUser(network->guid(), &onc_source);
1518   const NetworkPropertyUIData property_ui_data(onc_source);
1519
1520   base::DictionaryValue dictionary;
1521
1522   // Device hardware address
1523   const DeviceState* device = NetworkHandler::Get()->network_state_handler()->
1524       GetDeviceState(network->device_path());
1525   if (device)
1526     dictionary.SetString(kTagHardwareAddress, device->GetFormattedMacAddress());
1527
1528   // IP config
1529   scoped_ptr<base::DictionaryValue> ipconfig_dhcp(new base::DictionaryValue);
1530   ipconfig_dhcp->SetString(kIpConfigAddress, network->ip_address());
1531   ipconfig_dhcp->SetString(kIpConfigNetmask, network->GetNetmask());
1532   ipconfig_dhcp->SetString(kIpConfigGateway, network->gateway());
1533   std::string ipconfig_name_servers = network->GetDnsServersAsString();
1534   ipconfig_dhcp->SetString(kIpConfigNameServers, ipconfig_name_servers);
1535   ipconfig_dhcp->SetString(kIpConfigWebProxyAutoDiscoveryUrl,
1536                            network->web_proxy_auto_discovery_url().spec());
1537   SetValueDictionary(&dictionary,
1538                      kDictionaryIpConfig,
1539                      ipconfig_dhcp.release(),
1540                      property_ui_data);
1541
1542   std::string name_server_type = kNameServerTypeAutomatic;
1543   int automatic_ip_config = 0;
1544   scoped_ptr<base::DictionaryValue> static_ip_dict(
1545       BuildIPInfoDictionary(shill_properties, true, &automatic_ip_config));
1546   dictionary.SetBoolean(kIpConfigAutoConfig, automatic_ip_config == 0);
1547   DCHECK(automatic_ip_config == 3 || automatic_ip_config == 0)
1548       << "UI doesn't support automatic specification of individual "
1549       << "static IP parameters.";
1550   scoped_ptr<base::DictionaryValue> saved_ip_dict(
1551       BuildIPInfoDictionary(shill_properties, false, NULL));
1552   dictionary.Set(kDictionarySavedIp, saved_ip_dict.release());
1553
1554   // Determine what kind of name server setting we have by comparing the
1555   // StaticIP and Google values with the ipconfig values.
1556   std::string static_ip_nameservers;
1557   static_ip_dict->GetString(kIpConfigNameServers, &static_ip_nameservers);
1558   if (!static_ip_nameservers.empty() &&
1559       static_ip_nameservers == ipconfig_name_servers) {
1560     name_server_type = kNameServerTypeUser;
1561   }
1562   if (ipconfig_name_servers == kGoogleNameServers) {
1563     name_server_type = kNameServerTypeGoogle;
1564   }
1565   SetValueDictionary(&dictionary,
1566                      kDictionaryStaticIp,
1567                      static_ip_dict.release(),
1568                      property_ui_data);
1569
1570   std::string type = network->type();
1571   dictionary.SetString(kTagType, type);
1572   dictionary.SetString(kTagServicePath, network->path());
1573   dictionary.SetString(kTagNameServerType, name_server_type);
1574   dictionary.SetString(kTagNameServersGoogle, kGoogleNameServers);
1575
1576   // Only show proxy for remembered networks.
1577   dictionary.SetBoolean(kTagShowProxy, !network->profile_path().empty());
1578
1579   // Enable static ip config for Ethernet or WiFi.
1580   bool staticIPConfig = network->Matches(NetworkTypePattern::Ethernet()) ||
1581                         type == shill::kTypeWifi;
1582   dictionary.SetBoolean(kTagShowStaticIPConfig, staticIPConfig);
1583
1584   dictionary.SetBoolean(kTagShowPreferred, !network->profile_path().empty());
1585   int priority = 0;
1586   shill_properties.GetIntegerWithoutPathExpansion(
1587       shill::kPriorityProperty, &priority);
1588   bool preferred = priority > 0;
1589   SetValueDictionary(&dictionary, kTagPreferred,
1590                      new base::FundamentalValue(preferred),
1591                      property_ui_data);
1592
1593   NetworkPropertyUIData auto_connect_ui_data(onc_source);
1594   std::string onc_path_to_auto_connect;
1595   if (type == shill::kTypeWifi) {
1596     content::RecordAction(
1597         base::UserMetricsAction("Options_NetworkShowDetailsWifi"));
1598     if (network->IsConnectedState()) {
1599       content::RecordAction(
1600           base::UserMetricsAction("Options_NetworkShowDetailsWifiConnected"));
1601     }
1602     onc_path_to_auto_connect =
1603         ::onc::network_config::WifiProperty(::onc::wifi::kAutoConnect);
1604   } else if (type == shill::kTypeVPN) {
1605     content::RecordAction(
1606         base::UserMetricsAction("Options_NetworkShowDetailsVPN"));
1607     if (network->IsConnectedState()) {
1608       content::RecordAction(
1609           base::UserMetricsAction("Options_NetworkShowDetailsVPNConnected"));
1610     }
1611     onc_path_to_auto_connect = ::onc::network_config::VpnProperty(
1612         ::onc::vpn::kAutoConnect);
1613   } else if (type == shill::kTypeCellular) {
1614     content::RecordAction(
1615         base::UserMetricsAction("Options_NetworkShowDetailsCellular"));
1616     if (network->IsConnectedState()) {
1617       content::RecordAction(base::UserMetricsAction(
1618           "Options_NetworkShowDetailsCellularConnected"));
1619     }
1620   }
1621   if (!onc_path_to_auto_connect.empty()) {
1622     auto_connect_ui_data.ParseOncProperty(
1623         onc_source, onc, onc_path_to_auto_connect);
1624   }
1625   bool auto_connect = false;
1626   shill_properties.GetBooleanWithoutPathExpansion(
1627       shill::kAutoConnectProperty, &auto_connect);
1628   SetAutoconnectValueDictionary(network->IsPrivate(),
1629                                 onc_source,
1630                                 auto_connect,
1631                                 auto_connect_ui_data,
1632                                 &dictionary);
1633
1634   PopulateConnectionDetails(network, shill_properties, &dictionary);
1635
1636   // Show details dialog
1637   web_ui()->CallJavascriptFunction(kShowDetailedInfoFunction, dictionary);
1638 }
1639
1640 gfx::NativeWindow InternetOptionsHandler::GetNativeWindow() const {
1641   return web_ui()->GetWebContents()->GetTopLevelNativeWindow();
1642 }
1643
1644 void InternetOptionsHandler::NetworkCommandCallback(
1645     const base::ListValue* args) {
1646   std::string type;
1647   std::string service_path;
1648   std::string command;
1649   if (args->GetSize() != 3 ||
1650       !args->GetString(0, &type) ||
1651       !args->GetString(1, &service_path) ||
1652       !args->GetString(2, &command)) {
1653     NOTREACHED();
1654     return;
1655   }
1656
1657   // Process commands that do not require an existing network.
1658   if (command == kTagAddConnection) {
1659     if (CanAddNetworkType(type))
1660       AddConnection(type);
1661   } else if (command == kTagForget) {
1662     if (CanForgetNetworkType(type)) {
1663       NetworkHandler::Get()->network_configuration_handler()->
1664           RemoveConfiguration(
1665               service_path,
1666               base::Bind(&base::DoNothing),
1667               base::Bind(&ShillError, "NetworkCommand: " + command));
1668     }
1669   } else if (command == kTagOptions) {
1670     NetworkHandler::Get()->network_configuration_handler()->GetProperties(
1671         service_path,
1672         base::Bind(&InternetOptionsHandler::PopulateDictionaryDetailsCallback,
1673                    weak_factory_.GetWeakPtr()),
1674         base::Bind(&ShillError, "NetworkCommand: " + command));
1675   } else if (command == kTagConnect) {
1676     const NetworkState* network = GetNetworkState(service_path);
1677     if (network && network->type() == shill::kTypeWifi)
1678       content::RecordAction(
1679           base::UserMetricsAction("Options_NetworkConnectToWifi"));
1680     else if (network && network->type() == shill::kTypeVPN)
1681       content::RecordAction(
1682           base::UserMetricsAction("Options_NetworkConnectToVPN"));
1683     ash::network_connect::ConnectToNetwork(service_path, GetNativeWindow());
1684   } else if (command == kTagDisconnect) {
1685     const NetworkState* network = GetNetworkState(service_path);
1686     if (network && network->type() == shill::kTypeWifi)
1687       content::RecordAction(
1688           base::UserMetricsAction("Options_NetworkDisconnectWifi"));
1689     else if (network && network->type() == shill::kTypeVPN)
1690       content::RecordAction(
1691           base::UserMetricsAction("Options_NetworkDisconnectVPN"));
1692     NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
1693         service_path,
1694         base::Bind(&base::DoNothing),
1695         base::Bind(&ShillError, "NetworkCommand: " + command));
1696   } else if (command == kTagConfigure) {
1697     NetworkConfigView::Show(service_path, GetNativeWindow());
1698   } else if (command == kTagActivate && type == shill::kTypeCellular) {
1699     ash::network_connect::ActivateCellular(service_path);
1700     // Activation may update network properties (e.g. ActivationState), so
1701     // request them here in case they change.
1702     UpdateConnectionData(service_path);
1703   } else {
1704     VLOG(1) << "Unknown command: " << command;
1705     NOTREACHED();
1706   }
1707 }
1708
1709 void InternetOptionsHandler::AddConnection(const std::string& type) {
1710   if (type == shill::kTypeWifi) {
1711     content::RecordAction(
1712         base::UserMetricsAction("Options_NetworkJoinOtherWifi"));
1713     NetworkConfigView::ShowForType(shill::kTypeWifi, GetNativeWindow());
1714   } else if (type == shill::kTypeVPN) {
1715     content::RecordAction(
1716         base::UserMetricsAction("Options_NetworkJoinOtherVPN"));
1717     NetworkConfigView::ShowForType(shill::kTypeVPN, GetNativeWindow());
1718   } else if (type == shill::kTypeCellular) {
1719     ChooseMobileNetworkDialog::ShowDialog(GetNativeWindow());
1720   } else {
1721     NOTREACHED();
1722   }
1723 }
1724
1725 base::ListValue* InternetOptionsHandler::GetWiredList() {
1726   base::ListValue* list = new base::ListValue();
1727   const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
1728       FirstNetworkByType(NetworkTypePattern::Ethernet());
1729   if (!network)
1730     return list;
1731   list->Append(
1732       BuildNetworkDictionary(network,
1733                              web_ui()->GetDeviceScaleFactor(),
1734                              Profile::FromWebUI(web_ui())->GetPrefs()));
1735   return list;
1736 }
1737
1738 base::ListValue* InternetOptionsHandler::GetWirelessList() {
1739   base::ListValue* list = new base::ListValue();
1740
1741   NetworkStateHandler::NetworkStateList networks;
1742   NetworkHandler::Get()->network_state_handler()->GetNetworkListByType(
1743       NetworkTypePattern::Wireless(), &networks);
1744   for (NetworkStateHandler::NetworkStateList::const_iterator iter =
1745            networks.begin(); iter != networks.end(); ++iter) {
1746     list->Append(
1747         BuildNetworkDictionary(*iter,
1748                                web_ui()->GetDeviceScaleFactor(),
1749                                Profile::FromWebUI(web_ui())->GetPrefs()));
1750   }
1751
1752   return list;
1753 }
1754
1755 base::ListValue* InternetOptionsHandler::GetVPNList() {
1756   base::ListValue* list = new base::ListValue();
1757
1758   NetworkStateHandler::NetworkStateList networks;
1759   NetworkHandler::Get()->network_state_handler()->GetNetworkListByType(
1760       NetworkTypePattern::VPN(), &networks);
1761   for (NetworkStateHandler::NetworkStateList::const_iterator iter =
1762            networks.begin(); iter != networks.end(); ++iter) {
1763     list->Append(
1764         BuildNetworkDictionary(*iter,
1765                                web_ui()->GetDeviceScaleFactor(),
1766                                Profile::FromWebUI(web_ui())->GetPrefs()));
1767   }
1768
1769   return list;
1770 }
1771
1772 base::ListValue* InternetOptionsHandler::GetRememberedList() {
1773   base::ListValue* list = new base::ListValue();
1774
1775   NetworkStateHandler::FavoriteStateList favorites;
1776   NetworkHandler::Get()->network_state_handler()->GetFavoriteList(&favorites);
1777   for (NetworkStateHandler::FavoriteStateList::const_iterator iter =
1778            favorites.begin(); iter != favorites.end(); ++iter) {
1779     const FavoriteState* favorite = *iter;
1780     if (favorite->type() != shill::kTypeWifi &&
1781         favorite->type() != shill::kTypeVPN)
1782       continue;
1783     list->Append(
1784         BuildFavoriteDictionary(favorite,
1785                                 web_ui()->GetDeviceScaleFactor(),
1786                                 Profile::FromWebUI(web_ui())->GetPrefs()));
1787   }
1788
1789   return list;
1790 }
1791
1792 void InternetOptionsHandler::FillNetworkInfo(
1793     base::DictionaryValue* dictionary) {
1794   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
1795   dictionary->Set(kTagWiredList, GetWiredList());
1796   dictionary->Set(kTagWirelessList, GetWirelessList());
1797   dictionary->Set(kTagVpnList, GetVPNList());
1798   dictionary->Set(kTagRememberedList, GetRememberedList());
1799
1800   dictionary->SetBoolean(
1801       kTagWifiAvailable,
1802       handler->IsTechnologyAvailable(NetworkTypePattern::WiFi()));
1803   dictionary->SetBoolean(
1804       kTagWifiEnabled,
1805       handler->IsTechnologyEnabled(NetworkTypePattern::WiFi()));
1806
1807   dictionary->SetBoolean(
1808       kTagCellularAvailable,
1809       handler->IsTechnologyAvailable(NetworkTypePattern::Mobile()));
1810   dictionary->SetBoolean(
1811       kTagCellularEnabled,
1812       handler->IsTechnologyEnabled(NetworkTypePattern::Mobile()));
1813   const DeviceState* cellular =
1814       handler->GetDeviceStateByType(NetworkTypePattern::Mobile());
1815   dictionary->SetBoolean(
1816       kTagCellularSupportsScan,
1817       cellular && cellular->support_network_scan());
1818
1819   dictionary->SetBoolean(
1820       kTagWimaxAvailable,
1821       handler->IsTechnologyAvailable(NetworkTypePattern::Wimax()));
1822   dictionary->SetBoolean(
1823       kTagWimaxEnabled,
1824       handler->IsTechnologyEnabled(NetworkTypePattern::Wimax()));
1825 }
1826
1827 }  // namespace options
1828 }  // namespace chromeos