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 "chromeos/network/device_state.h"
20 #include "chromeos/network/network_device_handler.h"
21 #include "chromeos/network/network_event_log.h"
22 #include "chromeos/network/network_state_handler.h"
23 #include "chromeos/network/network_state_handler_observer.h"
24 #include "chromeos/network/shill_property_util.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 "grit/generated_resources.h"
31 #include "third_party/cros_system_api/dbus/service_constants.h"
32 #include "ui/base/l10n/l10n_util.h"
33 #include "ui/base/resource/resource_bundle.h"
35 using content::WebContents
;
36 using content::WebUIMessageHandler
;
42 // JS API callbacks names.
43 const char kJsApiCancel
[] = "cancel";
44 const char kJsApiConnect
[] = "connect";
45 const char kJsApiPageReady
[] = "pageReady";
47 // Page JS API function names.
48 const char kJsApiShowNetworks
[] = "mobile.ChooseNetwork.showNetworks";
49 const char kJsApiShowScanning
[] = "mobile.ChooseNetwork.showScanning";
51 // Network properties.
52 const char kNetworkIdProperty
[] = "networkId";
53 const char kOperatorNameProperty
[] = "operatorName";
54 const char kStatusProperty
[] = "status";
55 const char kTechnologyProperty
[] = "technology";
57 content::WebUIDataSource
* CreateChooseMobileNetworkUIHTMLSource() {
58 content::WebUIDataSource
* source
= content::WebUIDataSource::Create(
59 chrome::kChromeUIChooseMobileNetworkHost
);
61 source
->AddLocalizedString("chooseNetworkTitle",
62 IDS_NETWORK_CHOOSE_MOBILE_NETWORK
);
63 source
->AddLocalizedString("scanningMsgLine1",
64 IDS_NETWORK_SCANNING_FOR_MOBILE_NETWORKS
);
65 source
->AddLocalizedString("scanningMsgLine2",
66 IDS_NETWORK_SCANNING_THIS_MAY_TAKE_A_MINUTE
);
67 source
->AddLocalizedString("noMobileNetworks",
68 IDS_NETWORK_NO_MOBILE_NETWORKS
);
69 source
->AddLocalizedString("connect", IDS_OPTIONS_SETTINGS_CONNECT
);
70 source
->AddLocalizedString("cancel", IDS_CANCEL
);
72 source
->SetJsonPath("strings.js");
73 source
->AddResourcePath("choose_mobile_network.js",
74 IDR_CHOOSE_MOBILE_NETWORK_JS
);
75 source
->SetDefaultResource(IDR_CHOOSE_MOBILE_NETWORK_HTML
);
79 chromeos::NetworkDeviceHandler
* GetNetworkDeviceHandler() {
80 return chromeos::NetworkHandler::Get()->network_device_handler();
83 chromeos::NetworkStateHandler
* GetNetworkStateHandler() {
84 return chromeos::NetworkHandler::Get()->network_state_handler();
87 void NetworkOperationErrorCallback(
88 const std::string
& operation_name
,
89 const std::string
& error_name
,
90 scoped_ptr
<base::DictionaryValue
> error_data
) {
91 NET_LOG_ERROR("Operation failed: " + error_name
, operation_name
);
94 class ChooseMobileNetworkHandler
95 : public WebUIMessageHandler
,
96 public NetworkStateHandlerObserver
{
98 ChooseMobileNetworkHandler();
99 virtual ~ChooseMobileNetworkHandler();
101 // WebUIMessageHandler implementation.
102 virtual void RegisterMessages() OVERRIDE
;
104 // NetworkStateHandlerObserver implementation.
105 virtual void DeviceListChanged() OVERRIDE
;
108 // Handlers for JS WebUI messages.
109 void HandleCancel(const base::ListValue
* args
);
110 void HandleConnect(const base::ListValue
* args
);
111 void HandlePageReady(const base::ListValue
* args
);
113 std::string device_path_
;
114 base::ListValue networks_list_
;
116 bool has_pending_results_
;
118 DISALLOW_COPY_AND_ASSIGN(ChooseMobileNetworkHandler
);
121 // ChooseMobileNetworkHandler implementation.
123 ChooseMobileNetworkHandler::ChooseMobileNetworkHandler()
124 : is_page_ready_(false),
125 has_pending_results_(false) {
126 NetworkStateHandler
* handler
= GetNetworkStateHandler();
127 const DeviceState
* cellular
=
128 handler
->GetDeviceStateByType(NetworkTypePattern::Cellular());
131 "A cellular device is not available.",
132 "Cannot initiate a cellular network scan without a cellular device.");
135 handler
->AddObserver(this, FROM_HERE
);
136 device_path_
= cellular
->path();
137 GetNetworkDeviceHandler()->ProposeScan(
139 base::Bind(&base::DoNothing
),
140 base::Bind(&NetworkOperationErrorCallback
, "ProposeScan"));
143 ChooseMobileNetworkHandler::~ChooseMobileNetworkHandler() {
144 GetNetworkStateHandler()->RemoveObserver(this, FROM_HERE
);
147 void ChooseMobileNetworkHandler::RegisterMessages() {
148 web_ui()->RegisterMessageCallback(
150 base::Bind(&ChooseMobileNetworkHandler::HandleCancel
,
151 base::Unretained(this)));
152 web_ui()->RegisterMessageCallback(
154 base::Bind(&ChooseMobileNetworkHandler::HandleConnect
,
155 base::Unretained(this)));
156 web_ui()->RegisterMessageCallback(
158 base::Bind(&ChooseMobileNetworkHandler::HandlePageReady
,
159 base::Unretained(this)));
162 void ChooseMobileNetworkHandler::DeviceListChanged() {
163 const DeviceState
* cellular
= GetNetworkStateHandler()->GetDeviceState(
165 networks_list_
.Clear();
167 LOG(WARNING
) << "Cellular device with path '" << device_path_
171 if (cellular
->scanning()) {
172 NET_LOG_EVENT("ChooseMobileNetwork", "Device is scanning for networks.");
173 web_ui()->CallJavascriptFunction(kJsApiShowScanning
);
176 const DeviceState::CellularScanResults
& scan_results
=
177 cellular
->scan_results();
178 std::set
<std::string
> network_ids
;
179 for (DeviceState::CellularScanResults::const_iterator it
=
180 scan_results
.begin(); it
!= scan_results
.end(); ++it
) {
181 // We need to remove duplicates from the list because same network with
182 // different technologies are listed multiple times. But ModemManager
183 // Register API doesn't allow technology to be specified so just show unique
185 if (network_ids
.insert(it
->network_id
).second
) {
186 base::DictionaryValue
* network
= new base::DictionaryValue();
187 network
->SetString(kNetworkIdProperty
, it
->network_id
);
188 if (!it
->long_name
.empty())
189 network
->SetString(kOperatorNameProperty
, it
->long_name
);
190 else if (!it
->short_name
.empty())
191 network
->SetString(kOperatorNameProperty
, it
->short_name
);
193 network
->SetString(kOperatorNameProperty
, it
->network_id
);
194 network
->SetString(kStatusProperty
, it
->status
);
195 network
->SetString(kTechnologyProperty
, it
->technology
);
196 networks_list_
.Append(network
);
199 if (is_page_ready_
) {
200 web_ui()->CallJavascriptFunction(kJsApiShowNetworks
, networks_list_
);
201 networks_list_
.Clear();
202 has_pending_results_
= false;
204 has_pending_results_
= true;
208 void ChooseMobileNetworkHandler::HandleCancel(const base::ListValue
* args
) {
209 const size_t kConnectParamCount
= 0;
210 if (args
->GetSize() != kConnectParamCount
) {
215 // Switch to automatic mode.
216 GetNetworkDeviceHandler()->RegisterCellularNetwork(
218 "", // An empty string is for registration with the home network.
219 base::Bind(&base::DoNothing
),
220 base::Bind(&NetworkOperationErrorCallback
,
221 "Register in automatic mode."));
224 void ChooseMobileNetworkHandler::HandleConnect(const base::ListValue
* args
) {
225 std::string network_id
;
226 const size_t kConnectParamCount
= 1;
227 if (args
->GetSize() != kConnectParamCount
||
228 !args
->GetString(0, &network_id
)) {
233 GetNetworkDeviceHandler()->RegisterCellularNetwork(
236 base::Bind(&base::DoNothing
),
237 base::Bind(&NetworkOperationErrorCallback
,
238 std::string("Register to network: ") + network_id
));
241 void ChooseMobileNetworkHandler::HandlePageReady(const base::ListValue
* args
) {
242 const size_t kConnectParamCount
= 0;
243 if (args
->GetSize() != kConnectParamCount
) {
248 if (has_pending_results_
) {
249 web_ui()->CallJavascriptFunction(kJsApiShowNetworks
, networks_list_
);
250 networks_list_
.Clear();
251 has_pending_results_
= false;
253 is_page_ready_
= true;
258 ChooseMobileNetworkUI::ChooseMobileNetworkUI(content::WebUI
* web_ui
)
259 : WebUIController(web_ui
) {
260 ChooseMobileNetworkHandler
* handler
= new ChooseMobileNetworkHandler();
261 web_ui
->AddMessageHandler(handler
);
262 // Set up the "chrome://choose-mobile-network" source.
263 Profile
* profile
= Profile::FromWebUI(web_ui
);
264 content::WebUIDataSource::Add(
265 profile
, CreateChooseMobileNetworkUIHTMLSource());
268 } // namespace chromeos