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 "content/public/browser/web_contents.h"
25 #include "content/public/browser/web_ui.h"
26 #include "content/public/browser/web_ui_data_source.h"
27 #include "content/public/browser/web_ui_message_handler.h"
28 #include "grit/browser_resources.h"
29 #include "grit/generated_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->SetUseJsonJSFormatV2();
70 source->SetJsonPath("strings.js");
71 source->AddResourcePath("choose_mobile_network.js",
72 IDR_CHOOSE_MOBILE_NETWORK_JS);
73 source->SetDefaultResource(IDR_CHOOSE_MOBILE_NETWORK_HTML);
77 chromeos::NetworkDeviceHandler* GetNetworkDeviceHandler() {
78 return chromeos::NetworkHandler::Get()->network_device_handler();
81 chromeos::NetworkStateHandler* GetNetworkStateHandler() {
82 return chromeos::NetworkHandler::Get()->network_state_handler();
85 void NetworkOperationErrorCallback(
86 const std::string& operation_name,
87 const std::string& error_name,
88 scoped_ptr<base::DictionaryValue> error_data) {
89 NET_LOG_ERROR("Operation failed: " + error_name, operation_name);
92 class ChooseMobileNetworkHandler
93 : public WebUIMessageHandler,
94 public NetworkStateHandlerObserver {
96 ChooseMobileNetworkHandler();
97 virtual ~ChooseMobileNetworkHandler();
99 // WebUIMessageHandler implementation.
100 virtual void RegisterMessages() OVERRIDE;
102 // NetworkStateHandlerObserver implementation.
103 virtual void DeviceListChanged() OVERRIDE;
106 // Handlers for JS WebUI messages.
107 void HandleCancel(const base::ListValue* args);
108 void HandleConnect(const base::ListValue* args);
109 void HandlePageReady(const base::ListValue* args);
111 std::string device_path_;
112 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),
123 has_pending_results_(false) {
124 NetworkStateHandler* handler = GetNetworkStateHandler();
125 const DeviceState* cellular =
126 handler->GetDeviceStateByType(NetworkTypePattern::Cellular());
129 "A cellular device is not available.",
130 "Cannot initiate a cellular network scan without a cellular device.");
133 handler->AddObserver(this, FROM_HERE);
134 device_path_ = cellular->path();
135 GetNetworkDeviceHandler()->ProposeScan(
137 base::Bind(&base::DoNothing),
138 base::Bind(&NetworkOperationErrorCallback, "ProposeScan"));
141 ChooseMobileNetworkHandler::~ChooseMobileNetworkHandler() {
142 GetNetworkStateHandler()->RemoveObserver(this, FROM_HERE);
145 void ChooseMobileNetworkHandler::RegisterMessages() {
146 web_ui()->RegisterMessageCallback(
148 base::Bind(&ChooseMobileNetworkHandler::HandleCancel,
149 base::Unretained(this)));
150 web_ui()->RegisterMessageCallback(
152 base::Bind(&ChooseMobileNetworkHandler::HandleConnect,
153 base::Unretained(this)));
154 web_ui()->RegisterMessageCallback(
156 base::Bind(&ChooseMobileNetworkHandler::HandlePageReady,
157 base::Unretained(this)));
160 void ChooseMobileNetworkHandler::DeviceListChanged() {
161 const DeviceState* cellular = GetNetworkStateHandler()->GetDeviceState(
163 networks_list_.Clear();
165 LOG(WARNING) << "Cellular device with path '" << device_path_
169 if (cellular->scanning()) {
170 NET_LOG_EVENT("ChooseMobileNetwork", "Device is scanning for networks.");
171 web_ui()->CallJavascriptFunction(kJsApiShowScanning);
174 const DeviceState::CellularScanResults& scan_results =
175 cellular->scan_results();
176 std::set<std::string> network_ids;
177 for (DeviceState::CellularScanResults::const_iterator it =
178 scan_results.begin(); it != scan_results.end(); ++it) {
179 // We need to remove duplicates from the list because same network with
180 // different technologies are listed multiple times. But ModemManager
181 // Register API doesn't allow technology to be specified so just show unique
183 if (network_ids.insert(it->network_id).second) {
184 base::DictionaryValue* network = new base::DictionaryValue();
185 network->SetString(kNetworkIdProperty, it->network_id);
186 if (!it->long_name.empty())
187 network->SetString(kOperatorNameProperty, it->long_name);
188 else if (!it->short_name.empty())
189 network->SetString(kOperatorNameProperty, it->short_name);
191 network->SetString(kOperatorNameProperty, it->network_id);
192 network->SetString(kStatusProperty, it->status);
193 network->SetString(kTechnologyProperty, it->technology);
194 networks_list_.Append(network);
197 if (is_page_ready_) {
198 web_ui()->CallJavascriptFunction(kJsApiShowNetworks, networks_list_);
199 networks_list_.Clear();
200 has_pending_results_ = false;
202 has_pending_results_ = true;
206 void ChooseMobileNetworkHandler::HandleCancel(const base::ListValue* args) {
207 const size_t kConnectParamCount = 0;
208 if (args->GetSize() != kConnectParamCount) {
213 // Switch to automatic mode.
214 GetNetworkDeviceHandler()->RegisterCellularNetwork(
216 "", // An empty string is for registration with the home network.
217 base::Bind(&base::DoNothing),
218 base::Bind(&NetworkOperationErrorCallback,
219 "Register in automatic mode."));
222 void ChooseMobileNetworkHandler::HandleConnect(const base::ListValue* args) {
223 std::string network_id;
224 const size_t kConnectParamCount = 1;
225 if (args->GetSize() != kConnectParamCount ||
226 !args->GetString(0, &network_id)) {
231 GetNetworkDeviceHandler()->RegisterCellularNetwork(
234 base::Bind(&base::DoNothing),
235 base::Bind(&NetworkOperationErrorCallback,
236 std::string("Register to network: ") + network_id));
239 void ChooseMobileNetworkHandler::HandlePageReady(const base::ListValue* args) {
240 const size_t kConnectParamCount = 0;
241 if (args->GetSize() != kConnectParamCount) {
246 if (has_pending_results_) {
247 web_ui()->CallJavascriptFunction(kJsApiShowNetworks, networks_list_);
248 networks_list_.Clear();
249 has_pending_results_ = false;
251 is_page_ready_ = true;
256 ChooseMobileNetworkUI::ChooseMobileNetworkUI(content::WebUI* web_ui)
257 : WebUIController(web_ui) {
258 ChooseMobileNetworkHandler* handler = new ChooseMobileNetworkHandler();
259 web_ui->AddMessageHandler(handler);
260 // Set up the "chrome://choose-mobile-network" source.
261 Profile* profile = Profile::FromWebUI(web_ui);
262 content::WebUIDataSource::Add(
263 profile, CreateChooseMobileNetworkUIHTMLSource());
266 } // namespace chromeos