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