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.
5 #include "chrome/browser/ui/webui/chromeos/choose_mobile_network_ui.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_piece.h"
16 #include "base/values.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/common/url_constants.h"
19 #include "chrome/grit/generated_resources.h"
20 #include "chromeos/network/device_state.h"
21 #include "chromeos/network/network_device_handler.h"
22 #include "chromeos/network/network_event_log.h"
23 #include "chromeos/network/network_state_handler.h"
24 #include "chromeos/network/network_state_handler_observer.h"
25 #include "content/public/browser/web_contents.h"
26 #include "content/public/browser/web_ui.h"
27 #include "content/public/browser/web_ui_data_source.h"
28 #include "content/public/browser/web_ui_message_handler.h"
29 #include "grit/browser_resources.h"
30 #include "third_party/cros_system_api/dbus/service_constants.h"
32 using content::WebContents
;
33 using content::WebUIMessageHandler
;
39 // JS API callbacks names.
40 const char kJsApiCancel
[] = "cancel";
41 const char kJsApiConnect
[] = "connect";
42 const char kJsApiPageReady
[] = "pageReady";
44 // Page JS API function names.
45 const char kJsApiShowNetworks
[] = "mobile.ChooseNetwork.showNetworks";
46 const char kJsApiShowScanning
[] = "mobile.ChooseNetwork.showScanning";
48 // Network properties.
49 const char kNetworkIdProperty
[] = "networkId";
50 const char kOperatorNameProperty
[] = "operatorName";
51 const char kStatusProperty
[] = "status";
52 const char kTechnologyProperty
[] = "technology";
54 content::WebUIDataSource
* CreateChooseMobileNetworkUIHTMLSource() {
55 content::WebUIDataSource
* source
= content::WebUIDataSource::Create(
56 chrome::kChromeUIChooseMobileNetworkHost
);
58 source
->AddLocalizedString("chooseNetworkTitle",
59 IDS_NETWORK_CHOOSE_MOBILE_NETWORK
);
60 source
->AddLocalizedString("scanningMsgLine1",
61 IDS_NETWORK_SCANNING_FOR_MOBILE_NETWORKS
);
62 source
->AddLocalizedString("scanningMsgLine2",
63 IDS_NETWORK_SCANNING_THIS_MAY_TAKE_A_MINUTE
);
64 source
->AddLocalizedString("noMobileNetworks",
65 IDS_NETWORK_NO_MOBILE_NETWORKS
);
66 source
->AddLocalizedString("connect", IDS_OPTIONS_SETTINGS_CONNECT
);
67 source
->AddLocalizedString("cancel", IDS_CANCEL
);
69 source
->SetJsonPath("strings.js");
70 source
->AddResourcePath("choose_mobile_network.js",
71 IDR_CHOOSE_MOBILE_NETWORK_JS
);
72 source
->SetDefaultResource(IDR_CHOOSE_MOBILE_NETWORK_HTML
);
76 chromeos::NetworkDeviceHandler
* GetNetworkDeviceHandler() {
77 return chromeos::NetworkHandler::Get()->network_device_handler();
80 chromeos::NetworkStateHandler
* GetNetworkStateHandler() {
81 return chromeos::NetworkHandler::Get()->network_state_handler();
84 void NetworkOperationErrorCallback(
85 const std::string
& operation_name
,
86 const std::string
& error_name
,
87 scoped_ptr
<base::DictionaryValue
> error_data
) {
88 NET_LOG_ERROR("Operation failed: " + error_name
, operation_name
);
91 class ChooseMobileNetworkHandler
92 : public WebUIMessageHandler
,
93 public NetworkStateHandlerObserver
{
95 ChooseMobileNetworkHandler();
96 ~ChooseMobileNetworkHandler() override
;
98 // WebUIMessageHandler implementation.
99 void RegisterMessages() override
;
101 // NetworkStateHandlerObserver implementation.
102 void DeviceListChanged() override
;
105 // Handlers for JS WebUI messages.
106 void HandleCancel(const base::ListValue
* args
);
107 void HandleConnect(const base::ListValue
* args
);
108 void HandlePageReady(const base::ListValue
* args
);
110 std::string device_path_
;
111 base::ListValue networks_list_
;
114 bool has_pending_results_
;
116 DISALLOW_COPY_AND_ASSIGN(ChooseMobileNetworkHandler
);
119 // ChooseMobileNetworkHandler implementation.
121 ChooseMobileNetworkHandler::ChooseMobileNetworkHandler()
122 : is_page_ready_(false),
124 has_pending_results_(false) {
125 NetworkStateHandler
* handler
= GetNetworkStateHandler();
126 const DeviceState
* cellular
=
127 handler
->GetDeviceStateByType(NetworkTypePattern::Cellular());
130 "A cellular device is not available.",
131 "Cannot initiate a cellular network scan without a cellular device.");
134 handler
->AddObserver(this, FROM_HERE
);
135 device_path_
= cellular
->path();
136 GetNetworkDeviceHandler()->ProposeScan(
138 base::Bind(&base::DoNothing
),
139 base::Bind(&NetworkOperationErrorCallback
, "ProposeScan"));
142 ChooseMobileNetworkHandler::~ChooseMobileNetworkHandler() {
143 GetNetworkStateHandler()->RemoveObserver(this, FROM_HERE
);
146 void ChooseMobileNetworkHandler::RegisterMessages() {
147 web_ui()->RegisterMessageCallback(
149 base::Bind(&ChooseMobileNetworkHandler::HandleCancel
,
150 base::Unretained(this)));
151 web_ui()->RegisterMessageCallback(
153 base::Bind(&ChooseMobileNetworkHandler::HandleConnect
,
154 base::Unretained(this)));
155 web_ui()->RegisterMessageCallback(
157 base::Bind(&ChooseMobileNetworkHandler::HandlePageReady
,
158 base::Unretained(this)));
161 void ChooseMobileNetworkHandler::DeviceListChanged() {
162 const DeviceState
* cellular
= GetNetworkStateHandler()->GetDeviceState(
164 networks_list_
.Clear();
166 LOG(WARNING
) << "Cellular device with path '" << device_path_
170 if (cellular
->scanning()) {
171 NET_LOG_EVENT("ChooseMobileNetwork", "Device is scanning for networks.");
174 web_ui()->CallJavascriptFunction(kJsApiShowScanning
);
178 const DeviceState::CellularScanResults
& scan_results
=
179 cellular
->scan_results();
180 std::set
<std::string
> network_ids
;
181 for (DeviceState::CellularScanResults::const_iterator it
=
182 scan_results
.begin(); it
!= scan_results
.end(); ++it
) {
183 // We need to remove duplicates from the list because same network with
184 // different technologies are listed multiple times. But ModemManager
185 // Register API doesn't allow technology to be specified so just show unique
187 if (network_ids
.insert(it
->network_id
).second
) {
188 base::DictionaryValue
* network
= new base::DictionaryValue();
189 network
->SetString(kNetworkIdProperty
, it
->network_id
);
190 if (!it
->long_name
.empty())
191 network
->SetString(kOperatorNameProperty
, it
->long_name
);
192 else if (!it
->short_name
.empty())
193 network
->SetString(kOperatorNameProperty
, it
->short_name
);
195 network
->SetString(kOperatorNameProperty
, it
->network_id
);
196 network
->SetString(kStatusProperty
, it
->status
);
197 network
->SetString(kTechnologyProperty
, it
->technology
);
198 networks_list_
.Append(network
);
201 if (is_page_ready_
) {
202 web_ui()->CallJavascriptFunction(kJsApiShowNetworks
, networks_list_
);
203 networks_list_
.Clear();
204 has_pending_results_
= false;
206 has_pending_results_
= true;
210 void ChooseMobileNetworkHandler::HandleCancel(const base::ListValue
* args
) {
211 const size_t kConnectParamCount
= 0;
212 if (args
->GetSize() != kConnectParamCount
) {
217 // Switch to automatic mode.
218 GetNetworkDeviceHandler()->RegisterCellularNetwork(
220 "", // An empty string is for registration with the home network.
221 base::Bind(&base::DoNothing
),
222 base::Bind(&NetworkOperationErrorCallback
,
223 "Register in automatic mode."));
226 void ChooseMobileNetworkHandler::HandleConnect(const base::ListValue
* args
) {
227 std::string network_id
;
228 const size_t kConnectParamCount
= 1;
229 if (args
->GetSize() != kConnectParamCount
||
230 !args
->GetString(0, &network_id
)) {
235 GetNetworkDeviceHandler()->RegisterCellularNetwork(
238 base::Bind(&base::DoNothing
),
239 base::Bind(&NetworkOperationErrorCallback
,
240 std::string("Register to network: ") + network_id
));
243 void ChooseMobileNetworkHandler::HandlePageReady(const base::ListValue
* args
) {
244 const size_t kConnectParamCount
= 0;
245 if (args
->GetSize() != kConnectParamCount
) {
250 if (has_pending_results_
) {
251 web_ui()->CallJavascriptFunction(kJsApiShowNetworks
, networks_list_
);
252 networks_list_
.Clear();
253 has_pending_results_
= false;
254 } else if (scanning_
) {
255 web_ui()->CallJavascriptFunction(kJsApiShowScanning
);
257 is_page_ready_
= true;
262 ChooseMobileNetworkUI::ChooseMobileNetworkUI(content::WebUI
* web_ui
)
263 : WebUIController(web_ui
) {
264 ChooseMobileNetworkHandler
* handler
= new ChooseMobileNetworkHandler();
265 web_ui
->AddMessageHandler(handler
);
266 // Set up the "chrome://choose-mobile-network" source.
267 Profile
* profile
= Profile::FromWebUI(web_ui
);
268 content::WebUIDataSource::Add(
269 profile
, CreateChooseMobileNetworkUIHTMLSource());
272 } // namespace chromeos