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_
;
113 bool has_pending_results_
;
115 DISALLOW_COPY_AND_ASSIGN(ChooseMobileNetworkHandler
);
118 // ChooseMobileNetworkHandler implementation.
120 ChooseMobileNetworkHandler::ChooseMobileNetworkHandler()
121 : is_page_ready_(false),
122 has_pending_results_(false) {
123 NetworkStateHandler
* handler
= GetNetworkStateHandler();
124 const DeviceState
* cellular
=
125 handler
->GetDeviceStateByType(NetworkTypePattern::Cellular());
128 "A cellular device is not available.",
129 "Cannot initiate a cellular network scan without a cellular device.");
132 handler
->AddObserver(this, FROM_HERE
);
133 device_path_
= cellular
->path();
134 GetNetworkDeviceHandler()->ProposeScan(
136 base::Bind(&base::DoNothing
),
137 base::Bind(&NetworkOperationErrorCallback
, "ProposeScan"));
140 ChooseMobileNetworkHandler::~ChooseMobileNetworkHandler() {
141 GetNetworkStateHandler()->RemoveObserver(this, FROM_HERE
);
144 void ChooseMobileNetworkHandler::RegisterMessages() {
145 web_ui()->RegisterMessageCallback(
147 base::Bind(&ChooseMobileNetworkHandler::HandleCancel
,
148 base::Unretained(this)));
149 web_ui()->RegisterMessageCallback(
151 base::Bind(&ChooseMobileNetworkHandler::HandleConnect
,
152 base::Unretained(this)));
153 web_ui()->RegisterMessageCallback(
155 base::Bind(&ChooseMobileNetworkHandler::HandlePageReady
,
156 base::Unretained(this)));
159 void ChooseMobileNetworkHandler::DeviceListChanged() {
160 const DeviceState
* cellular
= GetNetworkStateHandler()->GetDeviceState(
162 networks_list_
.Clear();
164 LOG(WARNING
) << "Cellular device with path '" << device_path_
168 if (cellular
->scanning()) {
169 NET_LOG_EVENT("ChooseMobileNetwork", "Device is scanning for networks.");
170 web_ui()->CallJavascriptFunction(kJsApiShowScanning
);
173 const DeviceState::CellularScanResults
& scan_results
=
174 cellular
->scan_results();
175 std::set
<std::string
> network_ids
;
176 for (DeviceState::CellularScanResults::const_iterator it
=
177 scan_results
.begin(); it
!= scan_results
.end(); ++it
) {
178 // We need to remove duplicates from the list because same network with
179 // different technologies are listed multiple times. But ModemManager
180 // Register API doesn't allow technology to be specified so just show unique
182 if (network_ids
.insert(it
->network_id
).second
) {
183 base::DictionaryValue
* network
= new base::DictionaryValue();
184 network
->SetString(kNetworkIdProperty
, it
->network_id
);
185 if (!it
->long_name
.empty())
186 network
->SetString(kOperatorNameProperty
, it
->long_name
);
187 else if (!it
->short_name
.empty())
188 network
->SetString(kOperatorNameProperty
, it
->short_name
);
190 network
->SetString(kOperatorNameProperty
, it
->network_id
);
191 network
->SetString(kStatusProperty
, it
->status
);
192 network
->SetString(kTechnologyProperty
, it
->technology
);
193 networks_list_
.Append(network
);
196 if (is_page_ready_
) {
197 web_ui()->CallJavascriptFunction(kJsApiShowNetworks
, networks_list_
);
198 networks_list_
.Clear();
199 has_pending_results_
= false;
201 has_pending_results_
= true;
205 void ChooseMobileNetworkHandler::HandleCancel(const base::ListValue
* args
) {
206 const size_t kConnectParamCount
= 0;
207 if (args
->GetSize() != kConnectParamCount
) {
212 // Switch to automatic mode.
213 GetNetworkDeviceHandler()->RegisterCellularNetwork(
215 "", // An empty string is for registration with the home network.
216 base::Bind(&base::DoNothing
),
217 base::Bind(&NetworkOperationErrorCallback
,
218 "Register in automatic mode."));
221 void ChooseMobileNetworkHandler::HandleConnect(const base::ListValue
* args
) {
222 std::string network_id
;
223 const size_t kConnectParamCount
= 1;
224 if (args
->GetSize() != kConnectParamCount
||
225 !args
->GetString(0, &network_id
)) {
230 GetNetworkDeviceHandler()->RegisterCellularNetwork(
233 base::Bind(&base::DoNothing
),
234 base::Bind(&NetworkOperationErrorCallback
,
235 std::string("Register to network: ") + network_id
));
238 void ChooseMobileNetworkHandler::HandlePageReady(const base::ListValue
* args
) {
239 const size_t kConnectParamCount
= 0;
240 if (args
->GetSize() != kConnectParamCount
) {
245 if (has_pending_results_
) {
246 web_ui()->CallJavascriptFunction(kJsApiShowNetworks
, networks_list_
);
247 networks_list_
.Clear();
248 has_pending_results_
= false;
250 is_page_ready_
= true;
255 ChooseMobileNetworkUI::ChooseMobileNetworkUI(content::WebUI
* web_ui
)
256 : WebUIController(web_ui
) {
257 ChooseMobileNetworkHandler
* handler
= new ChooseMobileNetworkHandler();
258 web_ui
->AddMessageHandler(handler
);
259 // Set up the "chrome://choose-mobile-network" source.
260 Profile
* profile
= Profile::FromWebUI(web_ui
);
261 content::WebUIDataSource::Add(
262 profile
, CreateChooseMobileNetworkUIHTMLSource());
265 } // namespace chromeos