internet_options_handler.cc revision 2385ea399aae016c0806a4f9ef3c9cfe3d2a39df
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/shell.h"
14#include "ash/shell_delegate.h"
15#include "ash/system/chromeos/network/network_connect.h"
16#include "ash/system/chromeos/network/network_icon.h"
17#include "base/base64.h"
18#include "base/basictypes.h"
19#include "base/bind.h"
20#include "base/bind_helpers.h"
21#include "base/command_line.h"
22#include "base/i18n/time_formatting.h"
23#include "base/json/json_writer.h"
24#include "base/strings/string16.h"
25#include "base/strings/string_number_conversions.h"
26#include "base/strings/stringprintf.h"
27#include "base/strings/utf_string_conversions.h"
28#include "base/time/time.h"
29#include "base/values.h"
30#include "chrome/browser/browser_process.h"
31#include "chrome/browser/chrome_notification_types.h"
32#include "chrome/browser/chromeos/choose_mobile_network_dialog.h"
33#include "chrome/browser/chromeos/cros/network_library.h"
34#include "chrome/browser/chromeos/cros/network_property_ui_data.h"
35#include "chrome/browser/chromeos/enrollment_dialog_view.h"
36#include "chrome/browser/chromeos/login/user.h"
37#include "chrome/browser/chromeos/login/user_manager.h"
38#include "chrome/browser/chromeos/mobile_config.h"
39#include "chrome/browser/chromeos/options/network_config_view.h"
40#include "chrome/browser/chromeos/options/network_connect.h"
41#include "chrome/browser/chromeos/settings/cros_settings.h"
42#include "chrome/browser/chromeos/sim_dialog_delegate.h"
43#include "chrome/browser/chromeos/ui_proxy_config_service.h"
44#include "chrome/browser/profiles/profile_manager.h"
45#include "chrome/browser/ui/browser.h"
46#include "chrome/browser/ui/browser_finder.h"
47#include "chrome/browser/ui/browser_window.h"
48#include "chrome/browser/ui/host_desktop.h"
49#include "chrome/browser/ui/singleton_tabs.h"
50#include "chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h"
51#include "chrome/common/time_format.h"
52#include "chromeos/chromeos_switches.h"
53#include "chromeos/network/device_state.h"
54#include "chromeos/network/favorite_state.h"
55#include "chromeos/network/managed_network_configuration_handler.h"
56#include "chromeos/network/network_configuration_handler.h"
57#include "chromeos/network/network_connection_handler.h"
58#include "chromeos/network/network_device_handler.h"
59#include "chromeos/network/network_event_log.h"
60#include "chromeos/network/network_ip_config.h"
61#include "chromeos/network/network_profile.h"
62#include "chromeos/network/network_profile_handler.h"
63#include "chromeos/network/network_state.h"
64#include "chromeos/network/network_state_handler.h"
65#include "chromeos/network/network_ui_data.h"
66#include "chromeos/network/network_util.h"
67#include "chromeos/network/onc/onc_constants.h"
68#include "content/public/browser/notification_service.h"
69#include "content/public/browser/web_contents.h"
70#include "content/public/browser/web_contents_view.h"
71#include "content/public/browser/web_ui.h"
72#include "grit/ash_resources.h"
73#include "grit/ash_strings.h"
74#include "grit/chromium_strings.h"
75#include "grit/generated_resources.h"
76#include "grit/locale_settings.h"
77#include "grit/theme_resources.h"
78#include "third_party/cros_system_api/dbus/service_constants.h"
79#include "ui/base/l10n/l10n_util.h"
80#include "ui/base/layout.h"
81#include "ui/base/resource/resource_bundle.h"
82#include "ui/gfx/display.h"
83#include "ui/gfx/image/image_skia.h"
84#include "ui/gfx/screen.h"
85#include "ui/views/widget/widget.h"
86#include "ui/webui/web_ui_util.h"
87
88namespace chromeos {
89namespace options {
90
91namespace {
92
93// Keys for the network description dictionary passed to the web ui. Make sure
94// to keep the strings in sync with what the JavaScript side uses.
95const char kNetworkInfoKeyActivationState[] = "activationState";
96const char kNetworkInfoKeyConnectable[] = "connectable";
97const char kNetworkInfoKeyConnected[] = "connected";
98const char kNetworkInfoKeyConnecting[] = "connecting";
99const char kNetworkInfoKeyIconURL[] = "iconURL";
100const char kNetworkInfoKeyNetworkName[] = "networkName";
101const char kNetworkInfoKeyNetworkStatus[] = "networkStatus";
102const char kNetworkInfoKeyNetworkType[] = "networkType";
103const char kNetworkInfoKeyRemembered[] = "remembered";
104const char kNetworkInfoKeyServicePath[] = "servicePath";
105const char kNetworkInfoKeyPolicyManaged[] = "policyManaged";
106
107// These are keys for getting IP information from the web ui.
108const char kIpConfigAddress[] = "address";
109const char kIpConfigPrefixLength[] = "prefixLength";
110const char kIpConfigNetmask[] = "netmask";
111const char kIpConfigGateway[] = "gateway";
112const char kIpConfigNameServers[] = "nameServers";
113const char kIpConfigAutoConfig[] = "ipAutoConfig";
114
115// These are types of name server selections from the web ui.
116const char kNameServerTypeAutomatic[] = "automatic";
117const char kNameServerTypeGoogle[] = "google";
118const char kNameServerTypeUser[] = "user";
119
120// These are dictionary names used to send data to the web ui.
121const char kDictionaryIpConfig[] = "ipconfig";
122const char kDictionaryStaticIp[] = "staticIP";
123const char kDictionarySavedIp[] = "savedIP";
124
125// Google public name servers (DNS).
126const char kGoogleNameServers[] = "8.8.4.4,8.8.8.8";
127
128// Functions we call in JavaScript.
129const char kRefreshNetworkDataFunction[] =
130    "options.network.NetworkList.refreshNetworkData";
131const char kSetDefaultNetworkIconsFunction[] =
132    "options.network.NetworkList.setDefaultNetworkIcons";
133const char kShowDetailedInfoFunction[] =
134    "options.internet.DetailsInternetPage.showDetailedInfo";
135const char kUpdateConnectionDataFunction[] =
136    "options.internet.DetailsInternetPage.updateConnectionData";
137const char kUpdateCarrierFunction[] =
138    "options.internet.DetailsInternetPage.updateCarrier";
139const char kUpdateSecurityTabFunction[] =
140    "options.internet.DetailsInternetPage.updateSecurityTab";
141
142// These are used to register message handlers with JavaScript.
143const char kBuyDataPlanMessage[] = "buyDataPlan";
144const char kChangePinMessage[] = "changePin";
145const char kDisableCellularMessage[] = "disableCellular";
146const char kDisableWifiMessage[] = "disableWifi";
147const char kDisableWimaxMessage[] = "disableWimax";
148const char kEnableCellularMessage[] = "enableCellular";
149const char kEnableWifiMessage[] = "enableWifi";
150const char kEnableWimaxMessage[] = "enableWimax";
151const char kNetworkCommandMessage[] = "networkCommand";
152const char kRefreshNetworksMessage[] = "refreshNetworks";
153const char kSetApnMessage[] = "setApn";
154const char kSetAutoConnectMessage[] = "setAutoConnect";
155const char kSetCarrierMessage[] = "setCarrier";
156const char kSetIPConfigMessage[] = "setIPConfig";
157const char kSetPreferNetworkMessage[] = "setPreferNetwork";
158const char kSetServerHostname[] = "setServerHostname";
159const char kSetSimCardLockMessage[] = "setSimCardLock";
160const char kShowMorePlanInfoMessage[] = "showMorePlanInfo";
161
162// These are strings used to communicate with JavaScript.
163const char kTagActivate[] = "activate";
164const char kTagActivated[] = "activated";
165const char kTagActivationState[] = "activationState";
166const char kTagAddConnection[] = "add";
167const char kTagApn[] = "apn";
168const char kTagAutoConnect[] = "autoConnect";
169const char kTagBssid[] = "bssid";
170const char kTagCarrierSelectFlag[] = "showCarrierSelect";
171const char kTagCarrierUrl[] = "carrierUrl";
172const char kTagCellular[] = "cellular";
173const char kTagCellularAvailable[] = "cellularAvailable";
174const char kTagCellularEnabled[] = "cellularEnabled";
175const char kTagCellularSupportsScan[] = "cellularSupportsScan";
176const char kTagConfigure[] = "configure";
177const char kTagConnect[] = "connect";
178const char kTagConnected[] = "connected";
179const char kTagConnecting[] = "connecting";
180const char kTagConnectionState[] = "connectionState";
181const char kTagControlledBy[] = "controlledBy";
182const char kTagDataRemaining[] = "dataRemaining";
183const char kTagDeviceConnected[] = "deviceConnected";
184const char kTagDisableConnectButton[] = "disableConnectButton";
185const char kTagDisconnect[] = "disconnect";
186const char kTagEncryption[] = "encryption";
187const char kTagErrorState[] = "errorState";
188const char kTagEsn[] = "esn";
189const char kTagFirmwareRevision[] = "firmwareRevision";
190const char kTagForget[] = "forget";
191const char kTagFrequency[] = "frequency";
192const char kTagGsm[] = "gsm";
193const char kTagHardwareAddress[] = "hardwareAddress";
194const char kTagHardwareRevision[] = "hardwareRevision";
195const char kTagIdentity[] = "identity";
196const char kTagIccid[] = "iccid";
197const char kTagImei[] = "imei";
198const char kTagImsi[] = "imsi";
199const char kTagLanguage[] = "language";
200const char kTagLastGoodApn[] = "lastGoodApn";
201const char kTagLocalizedName[] = "localizedName";
202const char kTagManufacturer[] = "manufacturer";
203const char kTagMdn[] = "mdn";
204const char kTagMeid[] = "meid";
205const char kTagMin[] = "min";
206const char kTagModelId[] = "modelId";
207const char kTagName[] = "name";
208const char kTagNameServersGoogle[] = "nameServersGoogle";
209const char kTagNameServerType[] = "nameServerType";
210const char kTagNetworkId[] = "networkId";
211const char kTagNetworkName[] = "networkName";
212const char kTagNetworkTechnology[] = "networkTechnology";
213const char kTagOperatorCode[] = "operatorCode";
214const char kTagOperatorName[] = "operatorName";
215const char kTagOptions[] = "options";
216const char kTagPassword[] = "password";
217const char kTagPolicy[] = "policy";
218const char kTagPreferred[] = "preferred";
219const char kTagPrlVersion[] = "prlVersion";
220const char kTagProviderType[] = "providerType";
221const char kTagProviderApnList[] = "providerApnList";
222const char kTagRecommended[] = "recommended";
223const char kTagRecommendedValue[] = "recommendedValue";
224const char kTagRemembered[] = "remembered";
225const char kTagRememberedList[] = "rememberedList";
226const char kTagRestrictedPool[] = "restrictedPool";
227const char kTagRoamingState[] = "roamingState";
228const char kTagServerHostname[] = "serverHostname";
229const char kTagCarriers[] = "carriers";
230const char kTagCurrentCarrierIndex[] = "currentCarrierIndex";
231const char kTagServiceName[] = "serviceName";
232const char kTagServicePath[] = "servicePath";
233const char kTagShared[] = "shared";
234const char kTagShowActivateButton[] = "showActivateButton";
235const char kTagShowBuyButton[] = "showBuyButton";
236const char kTagShowPreferred[] = "showPreferred";
237const char kTagShowProxy[] = "showProxy";
238const char kTagShowStaticIPConfig[] = "showStaticIPConfig";
239const char kTagShowViewAccountButton[] = "showViewAccountButton";
240const char kTagSimCardLockEnabled[] = "simCardLockEnabled";
241const char kTagSsid[] = "ssid";
242const char kTagStrength[] = "strength";
243const char kTagSupportUrl[] = "supportUrl";
244const char kTagTrue[] = "true";
245const char kTagType[] = "type";
246const char kTagUsername[] = "username";
247const char kTagValue[] = "value";
248const char kTagVpn[] = "vpn";
249const char kTagVpnList[] = "vpnList";
250const char kTagWarning[] = "warning";
251const char kTagWifi[] = "wifi";
252const char kTagWifiAvailable[] = "wifiAvailable";
253const char kTagWifiEnabled[] = "wifiEnabled";
254const char kTagWimaxAvailable[] = "wimaxAvailable";
255const char kTagWimaxEnabled[] = "wimaxEnabled";
256const char kTagWiredList[] = "wiredList";
257const char kTagWirelessList[] = "wirelessList";
258
259const int kPreferredPriority = 1;
260
261void ShillError(const std::string& function,
262                const std::string& error_name,
263                scoped_ptr<base::DictionaryValue> error_data) {
264  NET_LOG_ERROR("Shill Error from InternetOptionsHandler: " + error_name,
265                function);
266}
267
268const NetworkState* GetNetworkState(const std::string& service_path) {
269  return NetworkHandler::Get()->network_state_handler()->
270      GetNetworkState(service_path);
271}
272
273void SetNetworkProperty(const std::string& service_path,
274                        const std::string& property,
275                        base::Value* value) {
276  NET_LOG_EVENT("SetNetworkProperty: " + property, service_path);
277  base::DictionaryValue properties;
278  properties.SetWithoutPathExpansion(property, value);
279  NetworkHandler::Get()->network_configuration_handler()->SetProperties(
280      service_path, properties,
281      base::Bind(&base::DoNothing),
282      base::Bind(&ShillError, "SetNetworkProperty"));
283}
284
285const base::DictionaryValue* FindPolicyForActiveUser(
286    const NetworkState* network,
287    onc::ONCSource* onc_source) {
288  const User* user = UserManager::Get()->GetActiveUser();
289  std::string username_hash = user ? user->username_hash() : std::string();
290  return NetworkHandler::Get()->managed_network_configuration_handler()
291      ->FindPolicyByGUID(username_hash, network->guid(), onc_source);
292}
293
294std::string ActivationStateString(const std::string& activation_state) {
295  int id;
296  if (activation_state == flimflam::kActivationStateActivated)
297    id = IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_ACTIVATED;
298  else if (activation_state == flimflam::kActivationStateActivating)
299    id = IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_ACTIVATING;
300  else if (activation_state == flimflam::kActivationStateNotActivated)
301    id = IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_NOT_ACTIVATED;
302  else if (activation_state == flimflam::kActivationStatePartiallyActivated)
303    id = IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_PARTIALLY_ACTIVATED;
304  else
305    id = IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_UNKNOWN;
306  return l10n_util::GetStringUTF8(id);
307}
308
309std::string RoamingStateString(const std::string& roaming_state) {
310  int id;
311  if (roaming_state == flimflam::kRoamingStateHome)
312    id = IDS_CHROMEOS_NETWORK_ROAMING_STATE_HOME;
313  else if (roaming_state == flimflam::kRoamingStateRoaming)
314    id = IDS_CHROMEOS_NETWORK_ROAMING_STATE_ROAMING;
315  else
316    id = IDS_CHROMEOS_NETWORK_ROAMING_STATE_UNKNOWN;
317  return l10n_util::GetStringUTF8(id);
318}
319
320std::string ConnectionStateString(const std::string& state) {
321  int id;
322  if (state == flimflam::kUnknownString)
323    id = IDS_CHROMEOS_NETWORK_STATE_UNKNOWN;
324  else if (state == flimflam::kStateIdle)
325    id = IDS_CHROMEOS_NETWORK_STATE_IDLE;
326  else if (state == flimflam::kStateCarrier)
327    id = IDS_CHROMEOS_NETWORK_STATE_CARRIER;
328  else if (state == flimflam::kStateAssociation)
329    id = IDS_CHROMEOS_NETWORK_STATE_ASSOCIATION;
330  else if (state == flimflam::kStateConfiguration)
331    id = IDS_CHROMEOS_NETWORK_STATE_CONFIGURATION;
332  else if (state == flimflam::kStateReady)
333    id = IDS_CHROMEOS_NETWORK_STATE_READY;
334  else if (state == flimflam::kStateDisconnect)
335    id = IDS_CHROMEOS_NETWORK_STATE_DISCONNECT;
336  else if (state == flimflam::kStateFailure)
337    id = IDS_CHROMEOS_NETWORK_STATE_FAILURE;
338  else if (state == flimflam::kStateActivationFailure)
339    id = IDS_CHROMEOS_NETWORK_STATE_ACTIVATION_FAILURE;
340  else if (state == flimflam::kStatePortal)
341    id = IDS_CHROMEOS_NETWORK_STATE_PORTAL;
342  else if (state == flimflam::kStateOnline)
343    id = IDS_CHROMEOS_NETWORK_STATE_ONLINE;
344  else
345    id = IDS_CHROMEOS_NETWORK_STATE_UNRECOGNIZED;
346  return l10n_util::GetStringUTF8(id);
347}
348
349std::string EncryptionString(const std::string& security,
350                             const std::string& eap_method) {
351  if (security == flimflam::kSecurityNone)
352    return "";
353  if (security == flimflam::kSecurityWpa)
354    return "WPA";
355  if (security == flimflam::kSecurityWep)
356    return "WEP";
357  if (security == flimflam::kSecurityRsn)
358    return "RSN";
359  if (security == flimflam::kSecurityPsk)
360    return "PSK";
361  if (security == flimflam::kSecurity8021x) {
362    std::string result = "8021X";
363    if (eap_method == flimflam::kEapMethodPEAP)
364      result += "PEAP";
365    else if (eap_method == flimflam::kEapMethodTLS)
366      result += "TLS";
367    else if (eap_method == flimflam::kEapMethodTTLS)
368      result += "TTLS";
369    else if (eap_method == flimflam::kEapMethodLEAP)
370      result += "LEAP";
371    return result;
372  }
373  return "Unknown";
374}
375
376std::string ProviderTypeString(
377    const std::string& provider_type,
378    const base::DictionaryValue& provider_properties) {
379  int id;
380  if (provider_type == flimflam::kProviderL2tpIpsec) {
381    std::string client_cert_id;
382    provider_properties.GetStringWithoutPathExpansion(
383        flimflam::kL2tpIpsecClientCertIdProperty, &client_cert_id);
384    if (client_cert_id.empty())
385      id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_PSK;
386    else
387      id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_USER_CERT;
388  } else if (provider_type == flimflam::kProviderOpenVpn) {
389    id = IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_OPEN_VPN;
390  } else {
391    id = IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN;
392  }
393  return l10n_util::GetStringUTF8(id);
394}
395
396// A helper class for building network information dictionaries to be sent to
397// the webui code.
398class NetworkInfoDictionary {
399 public:
400  // Sets properties based on |network| and sets an appropriate icon based
401  // on the network type and |icon_scale_factor|.
402  NetworkInfoDictionary(const NetworkState* network,
403                        ui::ScaleFactor icon_scale_factor);
404  NetworkInfoDictionary(const FavoriteState* network,
405                        ui::ScaleFactor icon_scale_factor);
406
407  // Builds the DictionaryValue representation from the previously set
408  // parameters. Ownership of the returned pointer is transferred to the caller.
409  base::DictionaryValue* BuildDictionary();
410
411 private:
412  void SetIcon(const gfx::ImageSkia& icon,
413               ui::ScaleFactor icon_scale_factor) {
414    gfx::ImageSkiaRep image_rep = icon.GetRepresentation(icon_scale_factor);
415    icon_url_ = icon.isNull() ? "" : webui::GetBitmapDataUrl(
416        image_rep.sk_bitmap());
417  }
418
419  std::string service_path_;
420  std::string icon_url_;
421  std::string name_;
422  bool connecting_;
423  bool connected_;
424  bool connectable_;
425  std::string connection_type_;
426  bool remembered_;
427  bool shared_;
428  std::string activation_state_;
429  bool policy_managed_;
430
431  DISALLOW_COPY_AND_ASSIGN(NetworkInfoDictionary);
432};
433
434NetworkInfoDictionary::NetworkInfoDictionary(const NetworkState* network,
435                                             ui::ScaleFactor icon_scale_factor)
436    : service_path_(network->path()),
437      name_(network->name()),
438      connecting_(network->IsConnectingState()),
439      connected_(network->IsConnectedState()),
440      connectable_(network->connectable()),
441      connection_type_(network->type()),
442      remembered_(false),
443      shared_(false),
444      activation_state_(network->activation_state()),
445      policy_managed_(network->IsManaged()) {
446  if (network->type() == flimflam::kTypeEthernet)
447    name_ = l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
448  gfx::ImageSkia icon = ash::network_icon::GetImageForNetwork(
449      network, ash::network_icon::ICON_TYPE_LIST);
450  SetIcon(icon, icon_scale_factor);
451}
452
453NetworkInfoDictionary::NetworkInfoDictionary(const FavoriteState* favorite,
454                                             ui::ScaleFactor icon_scale_factor)
455    : service_path_(favorite->path()),
456      name_(favorite->name()),
457      connecting_(false),
458      connected_(false),
459      connectable_(false),
460      connection_type_(favorite->type()),
461      remembered_(true),
462      shared_(!favorite->IsPrivate()),
463      policy_managed_(favorite->IsManaged()) {
464  if (favorite->type() == flimflam::kTypeEthernet)
465    name_ = l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
466  gfx::ImageSkia icon = ash::network_icon::GetImageForDisconnectedNetwork(
467      ash::network_icon::ICON_TYPE_LIST, favorite->type());
468  SetIcon(icon, icon_scale_factor);
469}
470
471base::DictionaryValue* NetworkInfoDictionary::BuildDictionary() {
472  std::string status;
473  if (remembered_) {
474    if (shared_)
475      status = l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_SHARED_NETWORK);
476  } else {
477    int id;
478    if (connected_)
479      id = IDS_STATUSBAR_NETWORK_DEVICE_CONNECTED;
480    else if (connecting_)
481      id = IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING;
482    else if (!connectable_)
483      id = IDS_STATUSBAR_NETWORK_DEVICE_NOT_CONFIGURED;
484    else
485      id = IDS_STATUSBAR_NETWORK_DEVICE_DISCONNECTED;
486    std::string status = l10n_util::GetStringUTF8(id);
487    if (connection_type_ == flimflam::kTypeCellular &&
488        activation_state_ != flimflam::kActivationStateActivated) {
489      status.append(" / ");
490      status.append(ActivationStateString(activation_state_));
491    }
492  }
493
494  scoped_ptr<base::DictionaryValue> network_info(new base::DictionaryValue());
495  network_info->SetString(kNetworkInfoKeyActivationState, activation_state_);
496  network_info->SetBoolean(kNetworkInfoKeyConnectable, connectable_);
497  network_info->SetBoolean(kNetworkInfoKeyConnected, connected_);
498  network_info->SetBoolean(kNetworkInfoKeyConnecting, connecting_);
499  network_info->SetString(kNetworkInfoKeyIconURL, icon_url_);
500  network_info->SetString(kNetworkInfoKeyNetworkName, name_);
501  network_info->SetString(kNetworkInfoKeyNetworkStatus, status);
502  network_info->SetString(kNetworkInfoKeyNetworkType, connection_type_);
503  network_info->SetBoolean(kNetworkInfoKeyRemembered, remembered_);
504  network_info->SetString(kNetworkInfoKeyServicePath, service_path_);
505  network_info->SetBoolean(kNetworkInfoKeyPolicyManaged, policy_managed_);
506  return network_info.release();
507}
508
509// Pulls IP information out of a shill service properties dictionary. If
510// |static_ip| is true, then it fetches "StaticIP.*" properties. If not, then it
511// fetches "SavedIP.*" properties. Caller must take ownership of returned
512// dictionary.  If non-NULL, |ip_parameters_set| returns a count of the number
513// of IP routing parameters that get set.
514base::DictionaryValue* BuildIPInfoDictionary(
515    const base::DictionaryValue& shill_properties,
516    bool static_ip,
517    int* routing_parameters_set) {
518  std::string address_key;
519  std::string prefix_len_key;
520  std::string gateway_key;
521  std::string name_servers_key;
522  if (static_ip) {
523    address_key = shill::kStaticIPAddressProperty;
524    prefix_len_key = shill::kStaticIPPrefixlenProperty;
525    gateway_key = shill::kStaticIPGatewayProperty;
526    name_servers_key = shill::kStaticIPNameServersProperty;
527  } else {
528    address_key = shill::kSavedIPAddressProperty;
529    prefix_len_key = shill::kSavedIPPrefixlenProperty;
530    gateway_key = shill::kSavedIPGatewayProperty;
531    name_servers_key = shill::kSavedIPNameServersProperty;
532  }
533
534  scoped_ptr<base::DictionaryValue> ip_info_dict(new base::DictionaryValue);
535  std::string address;
536  int routing_parameters = 0;
537  if (shill_properties.GetStringWithoutPathExpansion(address_key, &address)) {
538    ip_info_dict->SetString(kIpConfigAddress, address);
539    VLOG(2) << "Found " << address_key << ": " << address;
540    routing_parameters++;
541  }
542  int prefix_len = -1;
543  if (shill_properties.GetIntegerWithoutPathExpansion(
544      prefix_len_key, &prefix_len)) {
545    ip_info_dict->SetInteger(kIpConfigPrefixLength, prefix_len);
546    std::string netmask = network_util::PrefixLengthToNetmask(prefix_len);
547    ip_info_dict->SetString(kIpConfigNetmask, netmask);
548    VLOG(2) << "Found " << prefix_len_key << ": "
549            <<  prefix_len << " (" << netmask << ")";
550    routing_parameters++;
551  }
552  std::string gateway;
553  if (shill_properties.GetStringWithoutPathExpansion(gateway_key, &gateway)) {
554    ip_info_dict->SetString(kIpConfigGateway, gateway);
555    VLOG(2) << "Found " << gateway_key << ": " << gateway;
556    routing_parameters++;
557  }
558  if (routing_parameters_set)
559    *routing_parameters_set = routing_parameters;
560
561  std::string name_servers;
562  if (shill_properties.GetStringWithoutPathExpansion(
563      name_servers_key, &name_servers)) {
564    ip_info_dict->SetString(kIpConfigNameServers, name_servers);
565    VLOG(2) << "Found " << name_servers_key << ": " << name_servers;
566  }
567
568  return ip_info_dict.release();
569}
570
571static bool CanForgetNetworkType(const std::string& type) {
572  return type == flimflam::kTypeWifi ||
573         type == flimflam::kTypeWimax ||
574         type == flimflam::kTypeVPN;
575}
576
577static bool CanAddNetworkType(const std::string& type) {
578  return type == flimflam::kTypeWifi ||
579         type == flimflam::kTypeVPN ||
580         type == flimflam::kTypeCellular;
581}
582
583// Decorate pref value as CoreOptionsHandler::CreateValueForPref() does and
584// store it under |key| in |settings|. Takes ownership of |value|.
585void SetValueDictionary(base::DictionaryValue* settings,
586                        const char* key,
587                        base::Value* value,
588                        const NetworkPropertyUIData& ui_data) {
589  base::DictionaryValue* dict = new base::DictionaryValue();
590  // DictionaryValue::Set() takes ownership of |value|.
591  dict->Set(kTagValue, value);
592  const base::Value* recommended_value = ui_data.default_value();
593  if (ui_data.IsManaged())
594    dict->SetString(kTagControlledBy, kTagPolicy);
595  else if (recommended_value && recommended_value->Equals(value))
596    dict->SetString(kTagControlledBy, kTagRecommended);
597
598  if (recommended_value)
599    dict->Set(kTagRecommendedValue, recommended_value->DeepCopy());
600  settings->Set(key, dict);
601}
602
603std::string CopyStringFromDictionary(const base::DictionaryValue& source,
604                                     const std::string& src_key,
605                                     const std::string& dest_key,
606                                     base::DictionaryValue* dest) {
607  std::string string_value;
608  if (source.GetStringWithoutPathExpansion(src_key, &string_value))
609    dest->SetStringWithoutPathExpansion(dest_key, string_value);
610  return string_value;
611}
612
613void CopyIntegerFromDictionary(const base::DictionaryValue& source,
614                               const std::string& src_key,
615                               const std::string& dest_key,
616                               bool as_string,
617                               base::DictionaryValue* dest) {
618  int int_value;
619  if (!source.GetIntegerWithoutPathExpansion(src_key, &int_value))
620    return;
621  if (as_string) {
622    std::string str = base::StringPrintf("%d", int_value);
623    dest->SetStringWithoutPathExpansion(dest_key, str);
624  } else {
625    dest->SetIntegerWithoutPathExpansion(dest_key, int_value);
626  }
627}
628
629// Fills |dictionary| with the configuration details of |vpn|. |onc| is required
630// for augmenting the policy-managed information.
631void PopulateVPNDetails(const NetworkState* vpn,
632                        const base::DictionaryValue& shill_properties,
633                        base::DictionaryValue* dictionary) {
634  // Name and Remembered are set in PopulateConnectionDetails().
635  // Provider properties are stored in the "Provider" dictionary.
636  const base::DictionaryValue* provider_properties = NULL;
637  if (!shill_properties.GetDictionaryWithoutPathExpansion(
638          flimflam::kProviderProperty, &provider_properties)) {
639    LOG(ERROR) << "No provider properties for VPN: " << vpn->path();
640    return;
641  }
642  std::string provider_type;
643  provider_properties->GetStringWithoutPathExpansion(
644      flimflam::kTypeProperty, &provider_type);
645  dictionary->SetString(kTagProviderType,
646                        ProviderTypeString(provider_type,
647                                           *provider_properties));
648
649  std::string username;
650  if (provider_type == flimflam::kProviderOpenVpn) {
651    provider_properties->GetStringWithoutPathExpansion(
652        flimflam::kOpenVPNUserProperty, &username);
653  } else {
654    provider_properties->GetStringWithoutPathExpansion(
655        flimflam::kL2tpIpsecUserProperty, &username);
656  }
657  dictionary->SetString(kTagUsername, username);
658
659  onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
660  const base::DictionaryValue* onc = FindPolicyForActiveUser(vpn, &onc_source);
661
662  NetworkPropertyUIData hostname_ui_data;
663  hostname_ui_data.ParseOncProperty(
664      onc_source,
665      onc,
666      base::StringPrintf("%s.%s", onc::network_config::kVPN, onc::vpn::kHost));
667  std::string provider_host;
668  provider_properties->GetStringWithoutPathExpansion(
669      flimflam::kHostProperty, &provider_host);
670  SetValueDictionary(dictionary, kTagServerHostname,
671                     new base::StringValue(provider_host),
672                     hostname_ui_data);
673}
674
675// Given a list of supported carrier's by the device, return the index of
676// the carrier the device is currently using.
677int FindCurrentCarrierIndex(const base::ListValue* carriers,
678                            const DeviceState* device) {
679  DCHECK(carriers);
680  DCHECK(device);
681  bool gsm = (device->technology_family() == flimflam::kTechnologyFamilyGsm);
682  int index = 0;
683  for (base::ListValue::const_iterator it = carriers->begin();
684       it != carriers->end(); ++it, ++index) {
685    std::string value;
686    if (!(*it)->GetAsString(&value))
687      continue;
688    // For GSM devices the device name will be empty, so simply select
689    // the Generic UMTS carrier option if present.
690    if (gsm && (value == shill::kCarrierGenericUMTS))
691      return index;
692    // For other carriers, the service name will match the carrier name.
693    if (value == device->carrier())
694      return index;
695  }
696  return -1;
697}
698
699void PopulateWifiDetails(const NetworkState* wifi,
700                         const base::DictionaryValue& shill_properties,
701                         base::DictionaryValue* dictionary);
702// TODO(stevenjb): Move implementation here.
703
704void PopulateWimaxDetails(const NetworkState* wimax,
705                          const base::DictionaryValue& shill_properties,
706                          base::DictionaryValue* dictionary);
707// TODO(stevenjb): Move implementation here.
708
709void CreateDictionaryFromCellularApn(const base::DictionaryValue* apn,
710                                     base::DictionaryValue* dictionary);
711// TODO(stevenjb): Move implementation here.
712
713void PopulateCellularDetails(const NetworkState* cellular,
714                             const base::DictionaryValue& shill_properties,
715                             base::DictionaryValue* dictionary);
716// TODO(stevenjb): Move implementation here.
717
718void PopulateConnectionDetails(const NetworkState* network,
719                               const base::DictionaryValue& shill_properties,
720                               base::DictionaryValue* dictionary);
721// TODO(stevenjb): Move implementation here.
722
723// Helper methods for SetIPConfigProperties
724void AppendPropertyKeyIfPresent(const std::string& key,
725                                const base::DictionaryValue& old_properties,
726                                std::vector<std::string>* property_keys) {
727  if (old_properties.HasKey(key))
728    property_keys->push_back(key);
729}
730
731void AddStringPropertyIfChanged(const std::string& key,
732                                const std::string& new_value,
733                                const base::DictionaryValue& old_properties,
734                                base::DictionaryValue* new_properties) {
735  std::string old_value;
736  if (!old_properties.GetStringWithoutPathExpansion(key, &old_value) ||
737      new_value != old_value) {
738    new_properties->SetStringWithoutPathExpansion(key, new_value);
739  }
740}
741
742void AddIntegerPropertyIfChanged(const std::string& key,
743                                 int new_value,
744                                 const base::DictionaryValue& old_properties,
745                                 base::DictionaryValue* new_properties) {
746  int old_value;
747  if (!old_properties.GetIntegerWithoutPathExpansion(key, &old_value) ||
748      new_value != old_value) {
749    new_properties->SetIntegerWithoutPathExpansion(key, new_value);
750  }
751}
752
753}  // namespace
754
755InternetOptionsHandler::InternetOptionsHandler()
756    : weak_factory_(this) {
757  registrar_.Add(this, chrome::NOTIFICATION_REQUIRE_PIN_SETTING_CHANGE_ENDED,
758                 content::NotificationService::AllSources());
759  registrar_.Add(this, chrome::NOTIFICATION_ENTER_PIN_ENDED,
760                 content::NotificationService::AllSources());
761  NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);
762}
763
764InternetOptionsHandler::~InternetOptionsHandler() {
765  if (NetworkHandler::IsInitialized()) {
766    NetworkHandler::Get()->network_state_handler()->RemoveObserver(
767        this, FROM_HERE);
768  }
769}
770
771void InternetOptionsHandler::GetLocalizedValues(
772    base::DictionaryValue* localized_strings) {
773  DCHECK(localized_strings);
774
775  static OptionsStringResource resources[] = {
776
777    // Main settings page.
778
779    { "ethernetTitle", IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET },
780    { "wifiTitle", IDS_OPTIONS_SETTINGS_SECTION_TITLE_WIFI_NETWORK },
781    { "wimaxTitle", IDS_OPTIONS_SETTINGS_SECTION_TITLE_WIMAX_NETWORK },
782    { "cellularTitle", IDS_OPTIONS_SETTINGS_SECTION_TITLE_CELLULAR_NETWORK },
783    { "vpnTitle", IDS_OPTIONS_SETTINGS_SECTION_TITLE_PRIVATE_NETWORK },
784    { "networkNotConnected", IDS_OPTIONS_SETTINGS_NETWORK_NOT_CONNECTED },
785    { "networkConnected", IDS_CHROMEOS_NETWORK_STATE_READY },
786    { "joinOtherNetwork", IDS_OPTIONS_SETTINGS_NETWORK_OTHER },
787    { "networkOffline", IDS_OPTIONS_SETTINGS_NETWORK_OFFLINE },
788    { "networkDisabled", IDS_OPTIONS_SETTINGS_NETWORK_DISABLED },
789    { "networkOnline", IDS_OPTIONS_SETTINGS_NETWORK_ONLINE },
790    { "networkOptions", IDS_OPTIONS_SETTINGS_NETWORK_OPTIONS },
791    { "turnOffWifi", IDS_OPTIONS_SETTINGS_NETWORK_DISABLE_WIFI },
792    { "turnOffWimax", IDS_OPTIONS_SETTINGS_NETWORK_DISABLE_WIMAX },
793    { "turnOffCellular", IDS_OPTIONS_SETTINGS_NETWORK_DISABLE_CELLULAR },
794    { "disconnectNetwork", IDS_OPTIONS_SETTINGS_DISCONNECT },
795    { "preferredNetworks", IDS_OPTIONS_SETTINGS_PREFERRED_NETWORKS_LABEL },
796    { "preferredNetworksPage", IDS_OPTIONS_SETTINGS_PREFERRED_NETWORKS_TITLE },
797    { "useSharedProxies", IDS_OPTIONS_SETTINGS_USE_SHARED_PROXIES },
798    { "addConnectionTitle",
799      IDS_OPTIONS_SETTINGS_SECTION_TITLE_ADD_CONNECTION },
800    { "addConnectionWifi", IDS_OPTIONS_SETTINGS_ADD_CONNECTION_WIFI },
801    { "addConnectionVPN", IDS_STATUSBAR_NETWORK_ADD_VPN },
802    { "otherCellularNetworks", IDS_OPTIONS_SETTINGS_OTHER_CELLULAR_NETWORKS },
803    { "enableDataRoaming", IDS_OPTIONS_SETTINGS_ENABLE_DATA_ROAMING },
804    { "disableDataRoaming", IDS_OPTIONS_SETTINGS_DISABLE_DATA_ROAMING },
805    { "dataRoamingDisableToggleTooltip",
806      IDS_OPTIONS_SETTINGS_TOGGLE_DATA_ROAMING_RESTRICTION },
807    { "activateNetwork", IDS_STATUSBAR_NETWORK_DEVICE_ACTIVATE },
808
809    // Internet details dialog.
810
811    { "changeProxyButton",
812      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CHANGE_PROXY_BUTTON },
813    { "managedNetwork", IDS_OPTIONS_SETTINGS_MANAGED_NETWORK },
814    { "wifiNetworkTabLabel", IDS_OPTIONS_SETTINGS_INTERNET_TAB_CONNECTION },
815    { "vpnTabLabel", IDS_OPTIONS_SETTINGS_INTERNET_TAB_VPN },
816    { "cellularConnTabLabel", IDS_OPTIONS_SETTINGS_INTERNET_TAB_CONNECTION },
817    { "cellularDeviceTabLabel", IDS_OPTIONS_SETTINGS_INTERNET_TAB_DEVICE },
818    { "networkTabLabel", IDS_OPTIONS_SETTINGS_INTERNET_TAB_NETWORK },
819    { "securityTabLabel", IDS_OPTIONS_SETTINGS_INTERNET_TAB_SECURITY },
820    { "proxyTabLabel", IDS_OPTIONS_SETTINGS_INTERNET_TAB_PROXY },
821    { "connectionState", IDS_OPTIONS_SETTINGS_INTERNET_CONNECTION_STATE },
822    { "inetAddress", IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_ADDRESS },
823    { "inetNetmask", IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SUBNETMASK },
824    { "inetGateway", IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_GATEWAY },
825    { "inetNameServers", IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_DNSSERVER },
826    { "ipAutomaticConfiguration",
827        IDS_OPTIONS_SETTINGS_INTERNET_IP_AUTOMATIC_CONFIGURATION },
828    { "automaticNameServers",
829        IDS_OPTIONS_SETTINGS_INTERNET_AUTOMATIC_NAME_SERVERS },
830    { "userNameServer1", IDS_OPTIONS_SETTINGS_INTERNET_USER_NAME_SERVER_1 },
831    { "userNameServer2", IDS_OPTIONS_SETTINGS_INTERNET_USER_NAME_SERVER_2 },
832    { "userNameServer3", IDS_OPTIONS_SETTINGS_INTERNET_USER_NAME_SERVER_3 },
833    { "userNameServer4", IDS_OPTIONS_SETTINGS_INTERNET_USER_NAME_SERVER_4 },
834    { "googleNameServers", IDS_OPTIONS_SETTINGS_INTERNET_GOOGLE_NAME_SERVERS },
835    { "userNameServers", IDS_OPTIONS_SETTINGS_INTERNET_USER_NAME_SERVERS },
836    { "hardwareAddress",
837      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_HARDWARE_ADDRESS },
838    { "detailsInternetDismiss", IDS_CLOSE },
839    { "activateButton", IDS_OPTIONS_SETTINGS_ACTIVATE },
840    { "buyplanButton", IDS_OPTIONS_SETTINGS_BUY_PLAN },
841    { "connectButton", IDS_OPTIONS_SETTINGS_CONNECT },
842    { "configureButton", IDS_OPTIONS_SETTINGS_CONFIGURE },
843    { "disconnectButton", IDS_OPTIONS_SETTINGS_DISCONNECT },
844    { "viewAccountButton", IDS_STATUSBAR_NETWORK_VIEW_ACCOUNT },
845
846    { "wimaxConnTabLabel", IDS_OPTIONS_SETTINGS_INTERNET_TAB_WIMAX },
847
848    // Wifi Tab.
849
850    { "inetSsid", IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_ID },
851    { "inetBssid", IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_BSSID },
852    { "inetEncryption",
853      IDS_OPTIONS_SETTIGNS_INTERNET_OPTIONS_NETWORK_ENCRYPTION },
854    { "inetFrequency",
855      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_FREQUENCY },
856    { "inetFrequencyFormat",
857      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_FREQUENCY_MHZ },
858    { "inetSignalStrength",
859      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_STRENGTH },
860    { "inetSignalStrengthFormat",
861      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_STRENGTH_PERCENTAGE },
862    { "inetPassProtected",
863      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NET_PROTECTED },
864    { "inetNetworkShared",
865      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_SHARED },
866    { "inetPreferredNetwork",
867      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PREFER_NETWORK },
868    { "inetAutoConnectNetwork",
869      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_AUTO_CONNECT },
870    { "inetLogin", IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_LOGIN },
871    { "inetShowPass", IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SHOWPASSWORD },
872    { "inetPassPrompt", IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSWORD },
873    { "inetSsidPrompt", IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SSID },
874    { "inetStatus", IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_STATUS_TITLE },
875    { "inetConnect", IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CONNECT_TITLE },
876
877    // VPN Tab.
878
879    { "inetServiceName",
880      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVICE_NAME },
881    { "inetServerHostname",
882      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVER_HOSTNAME },
883    { "inetProviderType",
884      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PROVIDER_TYPE },
885    { "inetUsername", IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USERNAME },
886
887    // Cellular Tab.
888
889    { "serviceName", IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_SERVICE_NAME },
890    { "networkTechnology",
891      IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_NETWORK_TECHNOLOGY },
892    { "operatorName", IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_OPERATOR },
893    { "operatorCode", IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_OPERATOR_CODE },
894    { "activationState",
895      IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_ACTIVATION_STATE },
896    { "roamingState", IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_ROAMING_STATE },
897    { "restrictedPool",
898      IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_RESTRICTED_POOL },
899    { "errorState", IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_ERROR_STATE },
900    { "manufacturer", IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_MANUFACTURER },
901    { "modelId", IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_MODEL_ID },
902    { "firmwareRevision",
903      IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_FIRMWARE_REVISION },
904    { "hardwareRevision",
905      IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_HARDWARE_REVISION },
906    { "prlVersion", IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_PRL_VERSION },
907    { "cellularApnLabel", IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_APN },
908    { "cellularApnOther", IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_APN_OTHER },
909    { "cellularApnUsername",
910      IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_APN_USERNAME },
911    { "cellularApnPassword",
912      IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_APN_PASSWORD },
913    { "cellularApnUseDefault",
914      IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_APN_CLEAR },
915    { "cellularApnSet", IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_APN_SET },
916    { "cellularApnCancel", IDS_CANCEL },
917
918    // Security Tab.
919
920    { "accessSecurityTabLink",
921      IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_ACCESS_SECURITY_TAB },
922    { "lockSimCard", IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_LOCK_SIM_CARD },
923    { "changePinButton",
924      IDS_OPTIONS_SETTINGS_INTERNET_CELLULAR_CHANGE_PIN_BUTTON },
925  };
926
927  RegisterStrings(localized_strings, resources, arraysize(resources));
928
929  std::string owner;
930  chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
931  localized_strings->SetString("ownerUserId", UTF8ToUTF16(owner));
932
933  base::DictionaryValue* network_dictionary = new base::DictionaryValue;
934  FillNetworkInfo(network_dictionary);
935  localized_strings->Set("networkData", network_dictionary);
936}
937
938void InternetOptionsHandler::InitializePage() {
939  base::DictionaryValue dictionary;
940  dictionary.SetString(kTagCellular,
941      GetIconDataUrl(IDR_AURA_UBER_TRAY_NETWORK_BARS_DARK));
942  dictionary.SetString(kTagWifi,
943      GetIconDataUrl(IDR_AURA_UBER_TRAY_NETWORK_ARCS_DARK));
944  dictionary.SetString(kTagVpn,
945      GetIconDataUrl(IDR_AURA_UBER_TRAY_NETWORK_VPN));
946  web_ui()->CallJavascriptFunction(kSetDefaultNetworkIconsFunction,
947                                   dictionary);
948  NetworkHandler::Get()->network_state_handler()->RequestScan();
949}
950
951void InternetOptionsHandler::RegisterMessages() {
952  // Setup handlers specific to this panel.
953  web_ui()->RegisterMessageCallback(kNetworkCommandMessage,
954      base::Bind(&InternetOptionsHandler::NetworkCommandCallback,
955                 base::Unretained(this)));
956  web_ui()->RegisterMessageCallback(kRefreshNetworksMessage,
957      base::Bind(&InternetOptionsHandler::RefreshNetworksCallback,
958                 base::Unretained(this)));
959  web_ui()->RegisterMessageCallback(kSetPreferNetworkMessage,
960      base::Bind(&InternetOptionsHandler::SetPreferNetworkCallback,
961                 base::Unretained(this)));
962  web_ui()->RegisterMessageCallback(kSetAutoConnectMessage,
963      base::Bind(&InternetOptionsHandler::SetAutoConnectCallback,
964                 base::Unretained(this)));
965  web_ui()->RegisterMessageCallback(kSetIPConfigMessage,
966      base::Bind(&InternetOptionsHandler::SetIPConfigCallback,
967                 base::Unretained(this)));
968  web_ui()->RegisterMessageCallback(kEnableWifiMessage,
969      base::Bind(&InternetOptionsHandler::EnableWifiCallback,
970                 base::Unretained(this)));
971  web_ui()->RegisterMessageCallback(kDisableWifiMessage,
972      base::Bind(&InternetOptionsHandler::DisableWifiCallback,
973                 base::Unretained(this)));
974  web_ui()->RegisterMessageCallback(kEnableCellularMessage,
975      base::Bind(&InternetOptionsHandler::EnableCellularCallback,
976                 base::Unretained(this)));
977  web_ui()->RegisterMessageCallback(kDisableCellularMessage,
978      base::Bind(&InternetOptionsHandler::DisableCellularCallback,
979                 base::Unretained(this)));
980  web_ui()->RegisterMessageCallback(kEnableWimaxMessage,
981      base::Bind(&InternetOptionsHandler::EnableWimaxCallback,
982                 base::Unretained(this)));
983  web_ui()->RegisterMessageCallback(kDisableWimaxMessage,
984      base::Bind(&InternetOptionsHandler::DisableWimaxCallback,
985                 base::Unretained(this)));
986  web_ui()->RegisterMessageCallback(kBuyDataPlanMessage,
987      base::Bind(&InternetOptionsHandler::BuyDataPlanCallback,
988                 base::Unretained(this)));
989  web_ui()->RegisterMessageCallback(kShowMorePlanInfoMessage,
990      base::Bind(&InternetOptionsHandler::ShowMorePlanInfoCallback,
991                 base::Unretained(this)));
992  web_ui()->RegisterMessageCallback(kSetApnMessage,
993      base::Bind(&InternetOptionsHandler::SetApnCallback,
994                 base::Unretained(this)));
995  web_ui()->RegisterMessageCallback(kSetCarrierMessage,
996      base::Bind(&InternetOptionsHandler::SetCarrierCallback,
997                 base::Unretained(this)));
998  web_ui()->RegisterMessageCallback(kSetSimCardLockMessage,
999      base::Bind(&InternetOptionsHandler::SetSimCardLockCallback,
1000                 base::Unretained(this)));
1001  web_ui()->RegisterMessageCallback(kChangePinMessage,
1002      base::Bind(&InternetOptionsHandler::ChangePinCallback,
1003                 base::Unretained(this)));
1004  web_ui()->RegisterMessageCallback(kSetServerHostname,
1005      base::Bind(&InternetOptionsHandler::SetServerHostnameCallback,
1006                 base::Unretained(this)));
1007}
1008
1009void InternetOptionsHandler::EnableWifiCallback(const base::ListValue* args) {
1010  NetworkHandler::Get()->network_state_handler()->SetTechnologyEnabled(
1011      flimflam::kTypeWifi, true,
1012      base::Bind(&ShillError, "EnableWifiCallback"));
1013}
1014
1015void InternetOptionsHandler::DisableWifiCallback(const base::ListValue* args) {
1016  NetworkHandler::Get()->network_state_handler()->SetTechnologyEnabled(
1017      flimflam::kTypeWifi, false,
1018      base::Bind(&ShillError, "DisableWifiCallback"));
1019}
1020
1021void InternetOptionsHandler::EnableCellularCallback(
1022    const base::ListValue* args) {
1023  NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
1024  const DeviceState* device =
1025      handler->GetDeviceStateByType(flimflam::kTypeCellular);
1026  if (!device) {
1027    LOG(ERROR) << "Mobile device not found.";
1028    return;
1029  }
1030  if (!device->sim_lock_type().empty()) {
1031    SimDialogDelegate::ShowDialog(GetNativeWindow(),
1032                                  SimDialogDelegate::SIM_DIALOG_UNLOCK);
1033    return;
1034  }
1035  if (!handler->IsTechnologyEnabled(flimflam::kTypeCellular)) {
1036    handler->SetTechnologyEnabled(
1037        flimflam::kTypeCellular, true,
1038        base::Bind(&ShillError, "EnableCellularCallback"));
1039    return;
1040  }
1041  if (device->IsSimAbsent()) {
1042    MobileConfig* config = MobileConfig::GetInstance();
1043    if (config->IsReady()) {
1044      const MobileConfig::LocaleConfig* locale_config =
1045          config->GetLocaleConfig();
1046      if (locale_config) {
1047        std::string setup_url = locale_config->setup_url();
1048        if (!setup_url.empty()) {
1049          chrome::ShowSingletonTab(GetAppropriateBrowser(), GURL(setup_url));
1050          return;
1051        }
1052      }
1053    }
1054    // TODO(nkostylev): Show generic error message. http://crosbug.com/15444
1055  }
1056  LOG(ERROR) << "EnableCellularCallback called for enabled mobile device";
1057}
1058
1059void InternetOptionsHandler::DisableCellularCallback(
1060    const base::ListValue* args) {
1061  NetworkHandler::Get()->network_state_handler()->SetTechnologyEnabled(
1062      NetworkStateHandler::kMatchTypeMobile, false,
1063      base::Bind(&ShillError, "DisableCellularCallback"));
1064}
1065
1066void InternetOptionsHandler::EnableWimaxCallback(const base::ListValue* args) {
1067  NetworkHandler::Get()->network_state_handler()->SetTechnologyEnabled(
1068      flimflam::kTypeWimax, true,
1069      base::Bind(&ShillError, "EnableWimaxCallback"));
1070}
1071
1072void InternetOptionsHandler::DisableWimaxCallback(const base::ListValue* args) {
1073  NetworkHandler::Get()->network_state_handler()->SetTechnologyEnabled(
1074      flimflam::kTypeWimax, false,
1075      base::Bind(&ShillError, "DisableWimaxCallback"));
1076}
1077
1078void InternetOptionsHandler::ShowMorePlanInfoCallback(
1079    const base::ListValue* args) {
1080  if (!web_ui())
1081    return;
1082  std::string service_path;
1083  if (args->GetSize() != 1 || !args->GetString(0, &service_path)) {
1084    NOTREACHED();
1085    return;
1086  }
1087  network_connect::ShowMobileSetup(service_path);
1088}
1089
1090void InternetOptionsHandler::BuyDataPlanCallback(const base::ListValue* args) {
1091  if (!web_ui())
1092    return;
1093  std::string service_path;
1094  if (args->GetSize() != 1 || !args->GetString(0, &service_path)) {
1095    NOTREACHED();
1096    return;
1097  }
1098  network_connect::ShowMobileSetup(service_path);
1099}
1100
1101void InternetOptionsHandler::SetApnCallback(const base::ListValue* args) {
1102  std::string service_path;
1103  if (!args->GetString(0, &service_path)) {
1104    NOTREACHED();
1105    return;
1106  }
1107  NetworkHandler::Get()->network_configuration_handler()->GetProperties(
1108      service_path,
1109      base::Bind(&InternetOptionsHandler::SetApnProperties,
1110                 weak_factory_.GetWeakPtr(), base::Owned(args->DeepCopy())),
1111      base::Bind(&ShillError, "SetApnCallback"));
1112}
1113
1114void InternetOptionsHandler::SetApnProperties(
1115    const base::ListValue* args,
1116    const std::string& service_path,
1117    const base::DictionaryValue& shill_properties) {
1118  std::string apn, username, password;
1119  if (!args->GetString(1, &apn) ||
1120      !args->GetString(2, &username) ||
1121      !args->GetString(3, &password)) {
1122    NOTREACHED();
1123    return;
1124  }
1125  NET_LOG_EVENT("SetApnCallback", service_path);
1126
1127  if (apn.empty()) {
1128    std::vector<std::string> properties_to_clear;
1129    properties_to_clear.push_back(flimflam::kCellularApnProperty);
1130    NetworkHandler::Get()->network_configuration_handler()->ClearProperties(
1131      service_path, properties_to_clear,
1132      base::Bind(&base::DoNothing),
1133      base::Bind(&ShillError, "ClearCellularApnProperties"));
1134    return;
1135  }
1136
1137  const base::DictionaryValue* shill_apn_dict = NULL;
1138  std::string network_id;
1139  if (shill_properties.GetDictionaryWithoutPathExpansion(
1140          flimflam::kCellularApnProperty, &shill_apn_dict)) {
1141    shill_apn_dict->GetStringWithoutPathExpansion(
1142        flimflam::kApnNetworkIdProperty, &network_id);
1143  }
1144  base::DictionaryValue properties;
1145  base::DictionaryValue* apn_dict = new base::DictionaryValue;
1146  apn_dict->SetStringWithoutPathExpansion(flimflam::kApnProperty, apn);
1147  apn_dict->SetStringWithoutPathExpansion(flimflam::kApnNetworkIdProperty,
1148                                          network_id);
1149  apn_dict->SetStringWithoutPathExpansion(flimflam::kApnUsernameProperty,
1150                                          username);
1151  apn_dict->SetStringWithoutPathExpansion(flimflam::kApnPasswordProperty,
1152                                          password);
1153  properties.SetWithoutPathExpansion(flimflam::kCellularApnProperty, apn_dict);
1154  NetworkHandler::Get()->network_configuration_handler()->SetProperties(
1155      service_path, properties,
1156      base::Bind(&base::DoNothing),
1157      base::Bind(&ShillError, "SetApnProperties"));
1158}
1159
1160void InternetOptionsHandler::CarrierStatusCallback() {
1161  NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
1162  const DeviceState* device =
1163      handler->GetDeviceStateByType(flimflam::kTypeCellular);
1164  if (device && (device->carrier() == shill::kCarrierSprint)) {
1165    const NetworkState* network =
1166        handler->FirstNetworkByType(flimflam::kTypeCellular);
1167    if (network) {
1168      chromeos::network_connect::ActivateCellular(network->path());
1169      UpdateConnectionData(network->path());
1170    }
1171  }
1172  UpdateCarrier();
1173}
1174
1175void InternetOptionsHandler::SetCarrierCallback(const base::ListValue* args) {
1176  std::string service_path;
1177  std::string carrier;
1178  if (args->GetSize() != 2 ||
1179      !args->GetString(0, &service_path) ||
1180      !args->GetString(1, &carrier)) {
1181    NOTREACHED();
1182    return;
1183  }
1184  const DeviceState* device = NetworkHandler::Get()->network_state_handler()->
1185      GetDeviceStateByType(flimflam::kTypeCellular);
1186  if (!device) {
1187    LOG(WARNING) << "SetCarrierCallback with no cellular device.";
1188    return;
1189  }
1190  NetworkHandler::Get()->network_device_handler()->SetCarrier(
1191      device->path(),
1192      carrier,
1193      base::Bind(&InternetOptionsHandler::CarrierStatusCallback,
1194                 weak_factory_.GetWeakPtr()),
1195      base::Bind(&ShillError, "SetCarrierCallback"));
1196}
1197
1198void InternetOptionsHandler::SetSimCardLockCallback(
1199    const base::ListValue* args) {
1200  bool require_pin_new_value;
1201  if (!args->GetBoolean(0, &require_pin_new_value)) {
1202    NOTREACHED();
1203    return;
1204  }
1205  // 1. Bring up SIM unlock dialog, pass new RequirePin setting in URL.
1206  // 2. Dialog will ask for current PIN in any case.
1207  // 3. If card is locked it will first call PIN unlock operation
1208  // 4. Then it will call Set RequirePin, passing the same PIN.
1209  // 5. We'll get notified by REQUIRE_PIN_SETTING_CHANGE_ENDED notification.
1210  SimDialogDelegate::SimDialogMode mode;
1211  if (require_pin_new_value)
1212    mode = SimDialogDelegate::SIM_DIALOG_SET_LOCK_ON;
1213  else
1214    mode = SimDialogDelegate::SIM_DIALOG_SET_LOCK_OFF;
1215  SimDialogDelegate::ShowDialog(GetNativeWindow(), mode);
1216}
1217
1218void InternetOptionsHandler::ChangePinCallback(const base::ListValue* args) {
1219  SimDialogDelegate::ShowDialog(GetNativeWindow(),
1220      SimDialogDelegate::SIM_DIALOG_CHANGE_PIN);
1221}
1222
1223void InternetOptionsHandler::RefreshNetworksCallback(
1224    const base::ListValue* args) {
1225  NetworkHandler::Get()->network_state_handler()->RequestScan();
1226}
1227
1228std::string InternetOptionsHandler::GetIconDataUrl(int resource_id) const {
1229  gfx::ImageSkia* icon =
1230      ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
1231  gfx::ImageSkiaRep image_rep = icon->GetRepresentation(
1232      web_ui()->GetDeviceScaleFactor());
1233  return webui::GetBitmapDataUrl(image_rep.sk_bitmap());
1234}
1235
1236void InternetOptionsHandler::RefreshNetworkData() {
1237  base::DictionaryValue dictionary;
1238  FillNetworkInfo(&dictionary);
1239  web_ui()->CallJavascriptFunction(
1240      kRefreshNetworkDataFunction, dictionary);
1241}
1242
1243void InternetOptionsHandler::UpdateConnectionData(
1244    const std::string& service_path) {
1245  NetworkHandler::Get()->network_configuration_handler()->GetProperties(
1246      service_path,
1247      base::Bind(&InternetOptionsHandler::UpdateConnectionDataCallback,
1248                 weak_factory_.GetWeakPtr()),
1249      base::Bind(&ShillError, "UpdateConnectionData"));
1250}
1251
1252void InternetOptionsHandler::UpdateConnectionDataCallback(
1253    const std::string& service_path,
1254    const base::DictionaryValue& shill_properties) {
1255  const NetworkState* network = GetNetworkState(service_path);
1256  if (!network)
1257    return;
1258  base::DictionaryValue dictionary;
1259  PopulateConnectionDetails(network, shill_properties, &dictionary);
1260  web_ui()->CallJavascriptFunction(kUpdateConnectionDataFunction, dictionary);
1261}
1262
1263void InternetOptionsHandler::UpdateCarrier() {
1264  web_ui()->CallJavascriptFunction(kUpdateCarrierFunction);
1265}
1266
1267void InternetOptionsHandler::NetworkManagerChanged() {
1268  if (!web_ui())
1269    return;
1270  RefreshNetworkData();
1271}
1272
1273void InternetOptionsHandler::NetworkListChanged() {
1274  if (!web_ui())
1275    return;
1276  RefreshNetworkData();
1277}
1278
1279void InternetOptionsHandler::NetworkPropertiesUpdated(
1280    const NetworkState* network) {
1281  if (!web_ui())
1282    return;
1283  RefreshNetworkData();
1284  UpdateConnectionData(network->path());
1285}
1286
1287void InternetOptionsHandler::Observe(
1288    int type,
1289    const content::NotificationSource& source,
1290    const content::NotificationDetails& details) {
1291  OptionsPageUIHandler::Observe(type, source, details);
1292  if (type == chrome::NOTIFICATION_REQUIRE_PIN_SETTING_CHANGE_ENDED) {
1293    base::FundamentalValue require_pin(*content::Details<bool>(details).ptr());
1294    web_ui()->CallJavascriptFunction(
1295        kUpdateSecurityTabFunction, require_pin);
1296  } else if (type == chrome::NOTIFICATION_ENTER_PIN_ENDED) {
1297    // We make an assumption (which is valid for now) that the SIM
1298    // unlock dialog is put up only when the user is trying to enable
1299    // mobile data.
1300    bool cancelled = *content::Details<bool>(details).ptr();
1301    if (cancelled)
1302      RefreshNetworkData();
1303    // The case in which the correct PIN was entered and the SIM is
1304    // now unlocked is handled in NetworkMenuButton.
1305  }
1306}
1307
1308void InternetOptionsHandler::SetServerHostnameCallback(
1309    const base::ListValue* args) {
1310  std::string service_path, server_hostname;
1311  if (args->GetSize() < 2 ||
1312      !args->GetString(0, &service_path) ||
1313      !args->GetString(1, &server_hostname)) {
1314    NOTREACHED();
1315    return;
1316  }
1317  SetNetworkProperty(service_path, flimflam::kProviderHostProperty,
1318                     base::Value::CreateStringValue(server_hostname));
1319}
1320
1321void InternetOptionsHandler::SetPreferNetworkCallback(
1322    const base::ListValue* args) {
1323  std::string service_path, prefer_network_str;
1324  if (args->GetSize() < 2 ||
1325      !args->GetString(0, &service_path) ||
1326      !args->GetString(1, &prefer_network_str)) {
1327    NOTREACHED();
1328    return;
1329  }
1330  int priority = (prefer_network_str == kTagTrue) ? kPreferredPriority : 0;
1331  SetNetworkProperty(service_path, flimflam::kPriorityProperty,
1332                     base::Value::CreateIntegerValue(priority));
1333}
1334
1335void InternetOptionsHandler::SetAutoConnectCallback(
1336    const base::ListValue* args) {
1337  std::string service_path, auto_connect_str;
1338  if (args->GetSize() < 2 ||
1339      !args->GetString(0, &service_path) ||
1340      !args->GetString(1, &auto_connect_str)) {
1341    NOTREACHED();
1342    return;
1343  }
1344  bool auto_connect = auto_connect_str == kTagTrue;
1345  SetNetworkProperty(service_path, flimflam::kAutoConnectProperty,
1346                     base::Value::CreateBooleanValue(auto_connect));
1347}
1348
1349void InternetOptionsHandler::SetIPConfigCallback(const base::ListValue* args) {
1350  std::string service_path;
1351  if (!args->GetString(0, &service_path)) {
1352    NOTREACHED();
1353    return;
1354  }
1355  NetworkHandler::Get()->network_configuration_handler()->GetProperties(
1356      service_path,
1357      base::Bind(&InternetOptionsHandler::SetIPConfigProperties,
1358                 weak_factory_.GetWeakPtr(), base::Owned(args->DeepCopy())),
1359      base::Bind(&ShillError, "SetIPConfigCallback"));
1360}
1361
1362void InternetOptionsHandler::SetIPConfigProperties(
1363    const base::ListValue* args,
1364    const std::string& service_path,
1365    const base::DictionaryValue& shill_properties) {
1366  std::string address, netmask, gateway, name_server_type, name_servers;
1367  bool dhcp_for_ip;
1368  if (!args->GetBoolean(1, &dhcp_for_ip) ||
1369      !args->GetString(2, &address) ||
1370      !args->GetString(3, &netmask) ||
1371      !args->GetString(4, &gateway) ||
1372      !args->GetString(5, &name_server_type) ||
1373      !args->GetString(6, &name_servers)) {
1374    NOTREACHED();
1375    return;
1376  }
1377  NET_LOG_EVENT("SetIPConfigProperties", service_path);
1378
1379  std::vector<std::string> properties_to_clear;
1380  base::DictionaryValue properties_to_set;
1381
1382  if (dhcp_for_ip) {
1383    AppendPropertyKeyIfPresent(shill::kStaticIPAddressProperty,
1384                               shill_properties, &properties_to_clear);
1385    AppendPropertyKeyIfPresent(shill::kStaticIPPrefixlenProperty,
1386                               shill_properties, &properties_to_clear);
1387    AppendPropertyKeyIfPresent(shill::kStaticIPGatewayProperty,
1388                               shill_properties, &properties_to_clear);
1389  } else {
1390    AddStringPropertyIfChanged(
1391        shill::kStaticIPAddressProperty,
1392        address, shill_properties, &properties_to_set);
1393    int prefixlen = network_util::NetmaskToPrefixLength(netmask);
1394    if (prefixlen > 0) {
1395      LOG(ERROR) << "Invalid prefix length for: " << service_path;
1396      prefixlen = 0;
1397    }
1398    AddIntegerPropertyIfChanged(
1399        shill::kStaticIPPrefixlenProperty,
1400        prefixlen, shill_properties, &properties_to_set);
1401    AddStringPropertyIfChanged(
1402        shill::kStaticIPGatewayProperty,
1403        gateway, shill_properties, &properties_to_set);
1404  }
1405
1406  if (name_server_type == kNameServerTypeAutomatic) {
1407    AppendPropertyKeyIfPresent(shill::kStaticIPNameServersProperty,
1408                               shill_properties, &properties_to_clear);
1409  } else {
1410    if (name_server_type == kNameServerTypeGoogle)
1411      name_servers = kGoogleNameServers;
1412    AddStringPropertyIfChanged(
1413        shill::kStaticIPNameServersProperty,
1414        name_servers, shill_properties, &properties_to_set);
1415  }
1416
1417  if (!properties_to_clear.empty()) {
1418    NetworkHandler::Get()->network_configuration_handler()->ClearProperties(
1419      service_path, properties_to_clear,
1420      base::Bind(&base::DoNothing),
1421      base::Bind(&ShillError, "ClearIPConfigProperties"));
1422  }
1423  if (!properties_to_set.empty()) {
1424    NetworkHandler::Get()->network_configuration_handler()->SetProperties(
1425        service_path, properties_to_set,
1426        base::Bind(&base::DoNothing),
1427        base::Bind(&ShillError, "SetIPConfigProperties"));
1428  }
1429  std::string device_path;
1430  shill_properties.GetStringWithoutPathExpansion(
1431      flimflam::kDeviceProperty, &device_path);
1432  if (!device_path.empty()) {
1433    // TODO(stevenjb): Enable this once 18873007 has landed.
1434    // NetworkHandler::Get()->network_device_handler()->RequestRefreshIPConfigs(
1435    //     device_path);
1436  }
1437}
1438
1439void InternetOptionsHandler::PopulateDictionaryDetailsCallback(
1440    const std::string& service_path,
1441    const base::DictionaryValue& shill_properties) {
1442  const NetworkState* network = GetNetworkState(service_path);
1443  if (!network) {
1444    LOG(ERROR) << "Network properties not found: " << service_path;
1445    return;
1446  }
1447
1448  onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
1449  const base::DictionaryValue* onc =
1450      FindPolicyForActiveUser(network, &onc_source);
1451  const NetworkPropertyUIData property_ui_data(onc_source);
1452
1453  base::DictionaryValue dictionary;
1454
1455  // Device hardware address
1456  const DeviceState* device = NetworkHandler::Get()->network_state_handler()->
1457      GetDeviceState(network->device_path());
1458  if (device)
1459    dictionary.SetString(kTagHardwareAddress, device->mac_address());
1460
1461  // IP config
1462  scoped_ptr<base::DictionaryValue> ipconfig_dhcp(new base::DictionaryValue);
1463  ipconfig_dhcp->SetString(kIpConfigAddress, network->ip_address());
1464  ipconfig_dhcp->SetString(kIpConfigNetmask, network->GetNetmask());
1465  ipconfig_dhcp->SetString(kIpConfigGateway, network->gateway());
1466  std::string ipconfig_name_servers = network->GetDnsServersAsString();
1467  ipconfig_dhcp->SetString(kIpConfigNameServers, ipconfig_name_servers);
1468  SetValueDictionary(&dictionary,
1469                     kDictionaryIpConfig,
1470                     ipconfig_dhcp.release(),
1471                     property_ui_data);
1472
1473  std::string name_server_type = kNameServerTypeAutomatic;
1474  int automatic_ip_config = 0;
1475  scoped_ptr<base::DictionaryValue> static_ip_dict(
1476      BuildIPInfoDictionary(shill_properties, true, &automatic_ip_config));
1477  dictionary.SetBoolean(kIpConfigAutoConfig, automatic_ip_config == 0);
1478  DCHECK(automatic_ip_config == 3 || automatic_ip_config == 0)
1479      << "UI doesn't support automatic specification of individual "
1480      << "static IP parameters.";
1481  scoped_ptr<base::DictionaryValue> saved_ip_dict(
1482      BuildIPInfoDictionary(shill_properties, false, NULL));
1483  dictionary.Set(kDictionarySavedIp, saved_ip_dict.release());
1484
1485  // Determine what kind of name server setting we have by comparing the
1486  // StaticIP and Google values with the ipconfig values.
1487  std::string static_ip_nameservers;
1488  static_ip_dict->GetString(kIpConfigNameServers, &static_ip_nameservers);
1489  if (!static_ip_nameservers.empty() &&
1490      static_ip_nameservers == ipconfig_name_servers) {
1491    name_server_type = kNameServerTypeUser;
1492  }
1493  if (ipconfig_name_servers == kGoogleNameServers) {
1494    name_server_type = kNameServerTypeGoogle;
1495  }
1496  SetValueDictionary(&dictionary,
1497                     kDictionaryStaticIp,
1498                     static_ip_dict.release(),
1499                     property_ui_data);
1500
1501  std::string type = network->type();
1502  dictionary.SetString(kTagType, type);
1503  dictionary.SetString(kTagServicePath, network->path());
1504  dictionary.SetString(kTagNameServerType, name_server_type);
1505  dictionary.SetString(kTagNameServersGoogle, kGoogleNameServers);
1506
1507  // Only show proxy for remembered networks.
1508  dictionary.SetBoolean(kTagShowProxy, !network->profile_path().empty());
1509
1510  // Enable static ip config for ethernet. For wifi, enable if flag is set.
1511  bool staticIPConfig = type == flimflam::kTypeEthernet ||
1512      (type == flimflam::kTypeWifi &&
1513       CommandLine::ForCurrentProcess()->HasSwitch(
1514           chromeos::switches::kEnableStaticIPConfig));
1515  dictionary.SetBoolean(kTagShowStaticIPConfig, staticIPConfig);
1516
1517  dictionary.SetBoolean(kTagShowPreferred, !network->profile_path().empty());
1518  bool preferred = network->priority() > 0;
1519  SetValueDictionary(&dictionary, kTagPreferred,
1520                     new base::FundamentalValue(preferred),
1521                     property_ui_data);
1522
1523  NetworkPropertyUIData auto_connect_ui_data(onc_source);
1524  std::string onc_path_to_auto_connect;
1525  if (type == flimflam::kTypeWifi) {
1526    onc_path_to_auto_connect = base::StringPrintf(
1527        "%s.%s",
1528        onc::network_config::kWiFi,
1529        onc::wifi::kAutoConnect);
1530  } else if (type == flimflam::kTypeVPN) {
1531    onc_path_to_auto_connect = base::StringPrintf(
1532        "%s.%s",
1533        onc::network_config::kVPN,
1534        onc::vpn::kAutoConnect);
1535  }
1536  if (!onc_path_to_auto_connect.empty()) {
1537    auto_connect_ui_data.ParseOncProperty(
1538        onc_source, onc, onc_path_to_auto_connect);
1539  }
1540  SetValueDictionary(&dictionary, kTagAutoConnect,
1541                     new base::FundamentalValue(network->auto_connect()),
1542                     auto_connect_ui_data);
1543
1544  PopulateConnectionDetails(network, shill_properties, &dictionary);
1545
1546  // Show details dialog
1547  web_ui()->CallJavascriptFunction(kShowDetailedInfoFunction, dictionary);
1548}
1549
1550namespace {
1551
1552void PopulateConnectionDetails(const NetworkState* network,
1553                               const base::DictionaryValue& shill_properties,
1554                               base::DictionaryValue* dictionary) {
1555  dictionary->SetString(kNetworkInfoKeyServicePath, network->path());
1556  dictionary->SetString(kTagServiceName, network->name());
1557  dictionary->SetBoolean(kTagConnecting, network->IsConnectingState());
1558  dictionary->SetBoolean(kTagConnected, network->IsConnectedState());
1559  dictionary->SetString(kTagConnectionState,
1560                        ConnectionStateString(network->connection_state()));
1561  dictionary->SetString(kTagNetworkName, network->name());
1562  dictionary->SetString(kTagErrorState,
1563                        ash::network_connect::ErrorString(network->error()));
1564
1565  dictionary->SetBoolean(kTagRemembered, !network->profile_path().empty());
1566  bool shared = !network->IsPrivate();
1567  dictionary->SetBoolean(kTagShared, shared);
1568
1569  const std::string& type = network->type();
1570  const NetworkState* connected_network =
1571      NetworkHandler::Get()->network_state_handler()->ConnectedNetworkByType(
1572          type);
1573
1574  dictionary->SetBoolean(kTagDeviceConnected, connected_network != NULL);
1575
1576  if (type == flimflam::kTypeWifi)
1577    PopulateWifiDetails(network, shill_properties, dictionary);
1578  else if (type == flimflam::kTypeWimax)
1579    PopulateWimaxDetails(network, shill_properties, dictionary);
1580  else if (type == flimflam::kTypeCellular)
1581    PopulateCellularDetails(network, shill_properties, dictionary);
1582  else if (type == flimflam::kTypeVPN)
1583    PopulateVPNDetails(network, shill_properties, dictionary);
1584}
1585
1586void PopulateWifiDetails(const NetworkState* wifi,
1587                         const base::DictionaryValue& shill_properties,
1588                         base::DictionaryValue* dictionary) {
1589  dictionary->SetString(kTagSsid, wifi->name());
1590  dictionary->SetInteger(kTagStrength, wifi->signal_strength());
1591
1592  std::string security, eap_method;
1593  shill_properties.GetStringWithoutPathExpansion(
1594      flimflam::kSecurityProperty, &security);
1595  shill_properties.GetStringWithoutPathExpansion(
1596      flimflam::kEapMethodProperty, &eap_method);
1597  dictionary->SetString(kTagEncryption, EncryptionString(security, eap_method));
1598  CopyStringFromDictionary(shill_properties, flimflam::kWifiBSsid,
1599                           kTagBssid, dictionary);
1600  CopyIntegerFromDictionary(shill_properties, flimflam::kWifiFrequency,
1601                            kTagFrequency, false, dictionary);
1602}
1603
1604void PopulateWimaxDetails(const NetworkState* wimax,
1605                          const base::DictionaryValue& shill_properties,
1606                          base::DictionaryValue* dictionary) {
1607  dictionary->SetInteger(kTagStrength, wimax->signal_strength());
1608  CopyStringFromDictionary(shill_properties, flimflam::kEapIdentityProperty,
1609                           kTagIdentity, dictionary);
1610}
1611
1612void CreateDictionaryFromCellularApn(const base::DictionaryValue* apn,
1613                                     base::DictionaryValue* dictionary) {
1614  CopyStringFromDictionary(*apn, flimflam::kApnProperty,
1615                           kTagApn, dictionary);
1616  CopyStringFromDictionary(*apn, flimflam::kApnNetworkIdProperty,
1617                           kTagNetworkId, dictionary);
1618  CopyStringFromDictionary(*apn, flimflam::kApnUsernameProperty,
1619                           kTagUsername, dictionary);
1620  CopyStringFromDictionary(*apn, flimflam::kApnPasswordProperty,
1621                           kTagPassword, dictionary);
1622  CopyStringFromDictionary(*apn, flimflam::kApnNameProperty,
1623                           kTagName, dictionary);
1624  CopyStringFromDictionary(*apn, flimflam::kApnLocalizedNameProperty,
1625                           kTagLocalizedName, dictionary);
1626  CopyStringFromDictionary(*apn, flimflam::kApnLanguageProperty,
1627                           kTagLanguage, dictionary);
1628}
1629
1630void PopulateCellularDetails(const NetworkState* cellular,
1631                             const base::DictionaryValue& shill_properties,
1632                             base::DictionaryValue* dictionary) {
1633  dictionary->SetBoolean(kTagCarrierSelectFlag,
1634                         CommandLine::ForCurrentProcess()->HasSwitch(
1635                             chromeos::switches::kEnableCarrierSwitching));
1636  // Cellular network / connection settings.
1637  dictionary->SetString(kTagNetworkTechnology, cellular->network_technology());
1638  dictionary->SetString(kTagActivationState,
1639                        ActivationStateString(cellular->activation_state()));
1640  dictionary->SetString(kTagRoamingState,
1641                        RoamingStateString(cellular->roaming()));
1642  bool restricted = cellular->connection_state() == flimflam::kStatePortal;
1643  dictionary->SetString(kTagRestrictedPool,
1644                        restricted ?
1645                        l10n_util::GetStringUTF8(
1646                            IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL) :
1647                        l10n_util::GetStringUTF8(
1648                            IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL));
1649
1650  const base::DictionaryValue* serving_operator = NULL;
1651  if (shill_properties.GetDictionaryWithoutPathExpansion(
1652          flimflam::kServingOperatorProperty, &serving_operator)) {
1653    CopyStringFromDictionary(*serving_operator, flimflam::kOperatorNameKey,
1654                             kTagOperatorName, dictionary);
1655    CopyStringFromDictionary(*serving_operator, flimflam::kOperatorCodeKey,
1656                             kTagOperatorCode, dictionary);
1657  }
1658
1659  const base::DictionaryValue* olp = NULL;
1660  if (shill_properties.GetDictionaryWithoutPathExpansion(
1661          flimflam::kPaymentPortalProperty, &olp)) {
1662    std::string url;
1663    olp->GetStringWithoutPathExpansion(flimflam::kPaymentPortalURL, &url);
1664    dictionary->SetString(kTagSupportUrl, url);
1665  }
1666
1667  base::DictionaryValue* apn = new base::DictionaryValue;
1668  const base::DictionaryValue* source_apn = NULL;
1669  if (shill_properties.GetDictionaryWithoutPathExpansion(
1670          flimflam::kCellularApnProperty, &source_apn)) {
1671    CreateDictionaryFromCellularApn(source_apn, apn);
1672  }
1673  dictionary->Set(kTagApn, apn);
1674
1675  base::DictionaryValue* last_good_apn = new base::DictionaryValue;
1676  if (shill_properties.GetDictionaryWithoutPathExpansion(
1677          flimflam::kCellularLastGoodApnProperty, &source_apn)) {
1678    CreateDictionaryFromCellularApn(source_apn, last_good_apn);
1679  }
1680  dictionary->Set(kTagLastGoodApn, last_good_apn);
1681
1682  // These default to empty and are only set if device != NULL.
1683  std::string carrier_id;
1684  std::string mdn;
1685
1686  // Device settings.
1687  const DeviceState* device = NetworkHandler::Get()->network_state_handler()->
1688      GetDeviceState(cellular->device_path());
1689  if (device) {
1690    // TODO(stevenjb): Add NetworkDeviceHandler::GetProperties() and use that
1691    // to retrieve the complete dictionary of device properties, instead of
1692    // caching them (will be done for the new UI).
1693    const base::DictionaryValue& device_properties = device->properties();
1694    const NetworkPropertyUIData cellular_property_ui_data(
1695        cellular->onc_source());
1696    CopyStringFromDictionary(device_properties, flimflam::kManufacturerProperty,
1697                            kTagManufacturer, dictionary);
1698    CopyStringFromDictionary(device_properties, flimflam::kModelIDProperty,
1699                            kTagModelId, dictionary);
1700    CopyStringFromDictionary(device_properties,
1701                            flimflam::kFirmwareRevisionProperty,
1702                            kTagFirmwareRevision, dictionary);
1703    CopyStringFromDictionary(device_properties,
1704                            flimflam::kHardwareRevisionProperty,
1705                            kTagHardwareRevision, dictionary);
1706    CopyIntegerFromDictionary(device_properties, flimflam::kPRLVersionProperty,
1707                             kTagPrlVersion, true, dictionary);
1708    CopyStringFromDictionary(device_properties, flimflam::kMeidProperty,
1709                            kTagMeid, dictionary);
1710    CopyStringFromDictionary(device_properties, flimflam::kIccidProperty,
1711                            kTagIccid, dictionary);
1712    CopyStringFromDictionary(device_properties, flimflam::kImeiProperty,
1713                            kTagImei, dictionary);
1714    mdn = CopyStringFromDictionary(device_properties, flimflam::kMdnProperty,
1715                                   kTagMdn, dictionary);
1716    CopyStringFromDictionary(device_properties, flimflam::kImsiProperty,
1717                            kTagImsi, dictionary);
1718    CopyStringFromDictionary(device_properties, flimflam::kEsnProperty,
1719                            kTagEsn, dictionary);
1720    CopyStringFromDictionary(device_properties, flimflam::kMinProperty,
1721                            kTagMin, dictionary);
1722    std::string family;
1723    device_properties.GetStringWithoutPathExpansion(
1724        flimflam::kTechnologyFamilyProperty, &family);
1725    dictionary->SetBoolean(kTagGsm, family == flimflam::kNetworkTechnologyGsm);
1726
1727    SetValueDictionary(
1728        dictionary, kTagSimCardLockEnabled,
1729        new base::FundamentalValue(device->sim_lock_enabled()),
1730        cellular_property_ui_data);
1731
1732    carrier_id = device->home_provider_id();
1733
1734    MobileConfig* config = MobileConfig::GetInstance();
1735    if (config->IsReady()) {
1736      const MobileConfig::Carrier* carrier = config->GetCarrier(carrier_id);
1737      if (carrier && !carrier->top_up_url().empty())
1738        dictionary->SetString(kTagCarrierUrl, carrier->top_up_url());
1739    }
1740
1741    base::ListValue* apn_list_value = new base::ListValue();
1742    const base::ListValue* apn_list;
1743    if (device_properties.GetListWithoutPathExpansion(
1744            flimflam::kCellularApnListProperty, &apn_list)) {
1745      for (base::ListValue::const_iterator iter = apn_list->begin();
1746           iter != apn_list->end(); ++iter) {
1747        const base::DictionaryValue* dict;
1748        if ((*iter)->GetAsDictionary(&dict)) {
1749          base::DictionaryValue* apn = new base::DictionaryValue;
1750          CreateDictionaryFromCellularApn(dict, apn);
1751          apn_list_value->Append(apn);
1752        }
1753      }
1754    }
1755    SetValueDictionary(dictionary, kTagProviderApnList, apn_list_value,
1756                       cellular_property_ui_data);
1757    if (CommandLine::ForCurrentProcess()->HasSwitch(
1758            chromeos::switches::kEnableCarrierSwitching)) {
1759      const base::ListValue* supported_carriers;
1760      if (device_properties.GetListWithoutPathExpansion(
1761              shill::kSupportedCarriersProperty, &supported_carriers)) {
1762        dictionary->Set(kTagCarriers, supported_carriers->DeepCopy());
1763        dictionary->SetInteger(kTagCurrentCarrierIndex,
1764                               FindCurrentCarrierIndex(supported_carriers,
1765                                                       device));
1766      } else {
1767        // In case of any error, set the current carrier tag to -1 indicating
1768        // to the JS code to fallback to a single carrier.
1769        dictionary->SetInteger(kTagCurrentCarrierIndex, -1);
1770      }
1771    }
1772  }
1773
1774  // Set Cellular Buttons Visibility
1775  dictionary->SetBoolean(
1776      kTagDisableConnectButton,
1777      cellular->activation_state() == flimflam::kActivationStateActivating ||
1778      cellular->IsConnectingState());
1779
1780  if (cellular->activation_state() != flimflam::kActivationStateActivating &&
1781      cellular->activation_state() != flimflam::kActivationStateActivated) {
1782    dictionary->SetBoolean(kTagShowActivateButton, true);
1783  } else {
1784    const MobileConfig::Carrier* carrier =
1785        MobileConfig::GetInstance()->GetCarrier(carrier_id);
1786    if (carrier && carrier->show_portal_button()) {
1787      // The button should be shown for a LTE network even when the LTE network
1788      // is not connected, but CrOS is online. This is done to enable users to
1789      // update their plan even if they are out of credits.
1790      // The button should not be shown when the device's mdn is not set,
1791      // because the network's proper portal url cannot be generated without it
1792      const NetworkState* default_network =
1793          NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
1794      const std::string& technology = cellular->network_technology();
1795      bool force_show_view_account_button =
1796          (technology == flimflam::kNetworkTechnologyLte ||
1797           technology == flimflam::kNetworkTechnologyLteAdvanced) &&
1798          default_network &&
1799          !mdn.empty();
1800
1801      // The button will trigger ShowMorePlanInfoCallback() which will open
1802      // carrier specific portal.
1803      if (cellular->IsConnectedState() || force_show_view_account_button)
1804        dictionary->SetBoolean(kTagShowViewAccountButton, true);
1805    }
1806  }
1807}
1808
1809}  // namespace
1810
1811gfx::NativeWindow InternetOptionsHandler::GetNativeWindow() const {
1812  return web_ui()->GetWebContents()->GetView()->GetTopLevelNativeWindow();
1813}
1814
1815Browser* InternetOptionsHandler::GetAppropriateBrowser() {
1816  return chrome::FindOrCreateTabbedBrowser(
1817      ProfileManager::GetDefaultProfileOrOffTheRecord(),
1818      chrome::HOST_DESKTOP_TYPE_ASH);
1819}
1820
1821void InternetOptionsHandler::NetworkCommandCallback(
1822    const base::ListValue* args) {
1823  std::string type;
1824  std::string service_path;
1825  std::string command;
1826  if (args->GetSize() != 3 ||
1827      !args->GetString(0, &type) ||
1828      !args->GetString(1, &service_path) ||
1829      !args->GetString(2, &command)) {
1830    NOTREACHED();
1831    return;
1832  }
1833
1834  // Process commands that do not require an existing network.
1835  if (command == kTagAddConnection) {
1836    if (CanAddNetworkType(type))
1837      AddConnection(type);
1838  } else if (command == kTagForget) {
1839    if (CanForgetNetworkType(type)) {
1840      NetworkHandler::Get()->network_configuration_handler()->
1841          RemoveConfiguration(
1842              service_path,
1843              base::Bind(&base::DoNothing),
1844              base::Bind(&ShillError, "NetworkCommand: " + command));
1845    }
1846  } else if (command == kTagOptions) {
1847    NetworkHandler::Get()->network_configuration_handler()->GetProperties(
1848        service_path,
1849        base::Bind(&InternetOptionsHandler::PopulateDictionaryDetailsCallback,
1850                   weak_factory_.GetWeakPtr()),
1851        base::Bind(&ShillError, "NetworkCommand: " + command));
1852  } else if (command == kTagConnect) {
1853    network_connect::ConnectToNetwork(
1854        service_path, GetNativeWindow());
1855  } else if (command == kTagDisconnect) {
1856    NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
1857        service_path,
1858        base::Bind(&base::DoNothing),
1859        base::Bind(&ShillError, "NetworkCommand: " + command));
1860  } else if (command == kTagConfigure) {
1861    NetworkConfigView::ShowForPath(service_path, GetNativeWindow());
1862  } else if (command == kTagActivate && type == flimflam::kTypeCellular) {
1863    network_connect::ActivateCellular(service_path);
1864    // Activation may update network properties (e.g. ActivationState), so
1865    // request them here in case they change.
1866    UpdateConnectionData(service_path);
1867  } else {
1868    VLOG(1) << "Unknown command: " << command;
1869    NOTREACHED();
1870  }
1871}
1872
1873void InternetOptionsHandler::AddConnection(const std::string& type) {
1874  if (type == flimflam::kTypeWifi)
1875    NetworkConfigView::ShowForType(chromeos::TYPE_WIFI, GetNativeWindow());
1876  else if (type == flimflam::kTypeVPN)
1877    NetworkConfigView::ShowForType(chromeos::TYPE_VPN, GetNativeWindow());
1878  else if (type == flimflam::kTypeCellular)
1879    ChooseMobileNetworkDialog::ShowDialog(GetNativeWindow());
1880  else
1881    NOTREACHED();
1882}
1883
1884base::ListValue* InternetOptionsHandler::GetWiredList() {
1885  base::ListValue* list = new base::ListValue();
1886  const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
1887      FirstNetworkByType(flimflam::kTypeEthernet);
1888  if (!network)
1889    return list;
1890  NetworkInfoDictionary network_dict(network, web_ui()->GetDeviceScaleFactor());
1891  list->Append(network_dict.BuildDictionary());
1892  return list;
1893}
1894
1895base::ListValue* InternetOptionsHandler::GetWirelessList() {
1896  base::ListValue* list = new base::ListValue();
1897
1898  NetworkStateHandler::NetworkStateList networks;
1899  NetworkHandler::Get()->network_state_handler()->GetNetworkList(&networks);
1900  for (NetworkStateHandler::NetworkStateList::const_iterator iter =
1901           networks.begin(); iter != networks.end(); ++iter) {
1902    const NetworkState* network = *iter;
1903    if (network->type() != flimflam::kTypeWifi &&
1904        network->type() != flimflam::kTypeWimax &&
1905        network->type() != flimflam::kTypeCellular)
1906      continue;
1907    NetworkInfoDictionary network_dict(
1908        network, web_ui()->GetDeviceScaleFactor());
1909    list->Append(network_dict.BuildDictionary());
1910  }
1911
1912  return list;
1913}
1914
1915base::ListValue* InternetOptionsHandler::GetVPNList() {
1916  base::ListValue* list = new base::ListValue();
1917
1918  NetworkStateHandler::NetworkStateList networks;
1919  NetworkHandler::Get()->network_state_handler()->GetNetworkList(&networks);
1920  for (NetworkStateHandler::NetworkStateList::const_iterator iter =
1921           networks.begin(); iter != networks.end(); ++iter) {
1922    const NetworkState* network = *iter;
1923    if (network->type() != flimflam::kTypeVPN)
1924      continue;
1925    NetworkInfoDictionary network_dict(
1926        network, web_ui()->GetDeviceScaleFactor());
1927    list->Append(network_dict.BuildDictionary());
1928  }
1929
1930  return list;
1931}
1932
1933base::ListValue* InternetOptionsHandler::GetRememberedList() {
1934  base::ListValue* list = new base::ListValue();
1935
1936  NetworkStateHandler::FavoriteStateList favorites;
1937  NetworkHandler::Get()->network_state_handler()->GetFavoriteList(&favorites);
1938  for (NetworkStateHandler::FavoriteStateList::const_iterator iter =
1939           favorites.begin(); iter != favorites.end(); ++iter) {
1940    const FavoriteState* favorite = *iter;
1941    if (favorite->type() != flimflam::kTypeWifi &&
1942        favorite->type() != flimflam::kTypeVPN)
1943      continue;
1944    NetworkInfoDictionary network_dict(
1945        favorite, web_ui()->GetDeviceScaleFactor());
1946    list->Append(network_dict.BuildDictionary());
1947  }
1948
1949  return list;
1950}
1951
1952void InternetOptionsHandler::FillNetworkInfo(
1953    base::DictionaryValue* dictionary) {
1954  NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
1955  dictionary->Set(kTagWiredList, GetWiredList());
1956  dictionary->Set(kTagWirelessList, GetWirelessList());
1957  dictionary->Set(kTagVpnList, GetVPNList());
1958  dictionary->Set(kTagRememberedList, GetRememberedList());
1959
1960  dictionary->SetBoolean(kTagWifiAvailable,
1961                         handler->IsTechnologyAvailable(flimflam::kTypeWifi));
1962  dictionary->SetBoolean(kTagWifiEnabled,
1963                         handler->IsTechnologyEnabled(flimflam::kTypeWifi));
1964
1965  dictionary->SetBoolean(kTagCellularAvailable,
1966                         handler->IsTechnologyAvailable(
1967                             NetworkStateHandler::kMatchTypeMobile));
1968  dictionary->SetBoolean(kTagCellularEnabled,
1969                         handler->IsTechnologyEnabled(
1970                             NetworkStateHandler::kMatchTypeMobile));
1971  const DeviceState* cellular =
1972      handler->GetDeviceStateByType(NetworkStateHandler::kMatchTypeMobile);
1973  dictionary->SetBoolean(
1974      kTagCellularSupportsScan,
1975      cellular && cellular->support_network_scan());
1976
1977  dictionary->SetBoolean(kTagWimaxAvailable,
1978                         handler->IsTechnologyAvailable(flimflam::kTypeWimax));
1979  dictionary->SetBoolean(kTagWimaxEnabled,
1980                         handler->IsTechnologyEnabled(flimflam::kTypeWimax));
1981}
1982
1983}  // namespace options
1984}  // namespace chromeos
1985