choose_mobile_network_ui.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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/chromeos/choose_mobile_network_ui.h" 6 7#include <set> 8#include <string> 9 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" 34 35using content::WebContents; 36using content::WebUIMessageHandler; 37 38namespace chromeos { 39 40namespace { 41 42// JS API callbacks names. 43const char kJsApiCancel[] = "cancel"; 44const char kJsApiConnect[] = "connect"; 45const char kJsApiPageReady[] = "pageReady"; 46 47// Page JS API function names. 48const char kJsApiShowNetworks[] = "mobile.ChooseNetwork.showNetworks"; 49 50// Network properties. 51const char kNetworkIdProperty[] = "networkId"; 52const char kOperatorNameProperty[] = "operatorName"; 53const char kStatusProperty[] = "status"; 54const char kTechnologyProperty[] = "technology"; 55 56content::WebUIDataSource* CreateChooseMobileNetworkUIHTMLSource() { 57 content::WebUIDataSource* source = content::WebUIDataSource::Create( 58 chrome::kChromeUIChooseMobileNetworkHost); 59 60 source->AddLocalizedString("chooseNetworkTitle", 61 IDS_NETWORK_CHOOSE_MOBILE_NETWORK); 62 source->AddLocalizedString("scanningMsgLine1", 63 IDS_NETWORK_SCANNING_FOR_MOBILE_NETWORKS); 64 source->AddLocalizedString("scanningMsgLine2", 65 IDS_NETWORK_SCANNING_THIS_MAY_TAKE_A_MINUTE); 66 source->AddLocalizedString("noMobileNetworks", 67 IDS_NETWORK_NO_MOBILE_NETWORKS); 68 source->AddLocalizedString("connect", IDS_OPTIONS_SETTINGS_CONNECT); 69 source->AddLocalizedString("cancel", IDS_CANCEL); 70 71 source->SetJsonPath("strings.js"); 72 source->AddResourcePath("choose_mobile_network.js", 73 IDR_CHOOSE_MOBILE_NETWORK_JS); 74 source->SetDefaultResource(IDR_CHOOSE_MOBILE_NETWORK_HTML); 75 return source; 76} 77 78chromeos::NetworkDeviceHandler* GetNetworkDeviceHandler() { 79 return chromeos::NetworkHandler::Get()->network_device_handler(); 80} 81 82chromeos::NetworkStateHandler* GetNetworkStateHandler() { 83 return chromeos::NetworkHandler::Get()->network_state_handler(); 84} 85 86void NetworkOperationErrorCallback( 87 const std::string& operation_name, 88 const std::string& error_name, 89 scoped_ptr<base::DictionaryValue> error_data) { 90 NET_LOG_ERROR("Operation failed: " + error_name, operation_name); 91} 92 93class ChooseMobileNetworkHandler 94 : public WebUIMessageHandler, 95 public NetworkStateHandlerObserver { 96 public: 97 ChooseMobileNetworkHandler(); 98 virtual ~ChooseMobileNetworkHandler(); 99 100 // WebUIMessageHandler implementation. 101 virtual void RegisterMessages() OVERRIDE; 102 103 // NetworkStateHandlerObserver implementation. 104 virtual void DeviceListChanged() OVERRIDE; 105 106 private: 107 // Handlers for JS WebUI messages. 108 void HandleCancel(const ListValue* args); 109 void HandleConnect(const ListValue* args); 110 void HandlePageReady(const ListValue* args); 111 112 std::string device_path_; 113 ListValue networks_list_; 114 bool is_page_ready_; 115 bool has_pending_results_; 116 117 DISALLOW_COPY_AND_ASSIGN(ChooseMobileNetworkHandler); 118}; 119 120// ChooseMobileNetworkHandler implementation. 121 122ChooseMobileNetworkHandler::ChooseMobileNetworkHandler() 123 : is_page_ready_(false), 124 has_pending_results_(false) { 125 NetworkStateHandler* handler = GetNetworkStateHandler(); 126 const DeviceState* cellular = 127 handler->GetDeviceStateByType(NetworkTypePattern::Cellular()); 128 if (!cellular) { 129 NET_LOG_ERROR( 130 "A cellular device is not available.", 131 "Cannot initiate a cellular network scan without a cellular device."); 132 return; 133 } 134 handler->AddObserver(this, FROM_HERE); 135 device_path_ = cellular->path(); 136 GetNetworkDeviceHandler()->ProposeScan( 137 device_path_, 138 base::Bind(&base::DoNothing), 139 base::Bind(&NetworkOperationErrorCallback, "ProposeScan")); 140} 141 142ChooseMobileNetworkHandler::~ChooseMobileNetworkHandler() { 143 GetNetworkStateHandler()->RemoveObserver(this, FROM_HERE); 144} 145 146void ChooseMobileNetworkHandler::RegisterMessages() { 147 web_ui()->RegisterMessageCallback( 148 kJsApiCancel, 149 base::Bind(&ChooseMobileNetworkHandler::HandleCancel, 150 base::Unretained(this))); 151 web_ui()->RegisterMessageCallback( 152 kJsApiConnect, 153 base::Bind(&ChooseMobileNetworkHandler::HandleConnect, 154 base::Unretained(this))); 155 web_ui()->RegisterMessageCallback( 156 kJsApiPageReady, 157 base::Bind(&ChooseMobileNetworkHandler::HandlePageReady, 158 base::Unretained(this))); 159} 160 161void ChooseMobileNetworkHandler::DeviceListChanged() { 162 const DeviceState* cellular = GetNetworkStateHandler()->GetDeviceState( 163 device_path_); 164 networks_list_.Clear(); 165 if (!cellular) { 166 LOG(WARNING) << "Cellular device with path '" << device_path_ 167 << "' disappeared."; 168 return; 169 } 170 const DeviceState::CellularScanResults& scan_results = 171 cellular->scan_results(); 172 std::set<std::string> network_ids; 173 for (DeviceState::CellularScanResults::const_iterator it = 174 scan_results.begin(); it != scan_results.end(); ++it) { 175 // We need to remove duplicates from the list because same network with 176 // different technologies are listed multiple times. But ModemManager 177 // Register API doesn't allow technology to be specified so just show unique 178 // network in UI. 179 if (network_ids.insert(it->network_id).second) { 180 DictionaryValue* network = new DictionaryValue(); 181 network->SetString(kNetworkIdProperty, it->network_id); 182 if (!it->long_name.empty()) 183 network->SetString(kOperatorNameProperty, it->long_name); 184 else if (!it->short_name.empty()) 185 network->SetString(kOperatorNameProperty, it->short_name); 186 else 187 network->SetString(kOperatorNameProperty, it->network_id); 188 network->SetString(kStatusProperty, it->status); 189 network->SetString(kTechnologyProperty, it->technology); 190 networks_list_.Append(network); 191 } 192 } 193 if (is_page_ready_) { 194 web_ui()->CallJavascriptFunction(kJsApiShowNetworks, networks_list_); 195 networks_list_.Clear(); 196 has_pending_results_ = false; 197 } else { 198 has_pending_results_ = true; 199 } 200} 201 202void ChooseMobileNetworkHandler::HandleCancel(const ListValue* args) { 203 const size_t kConnectParamCount = 0; 204 if (args->GetSize() != kConnectParamCount) { 205 NOTREACHED(); 206 return; 207 } 208 209 // Switch to automatic mode. 210 GetNetworkDeviceHandler()->RegisterCellularNetwork( 211 device_path_, 212 "", // An empty string is for registration with the home network. 213 base::Bind(&base::DoNothing), 214 base::Bind(&NetworkOperationErrorCallback, 215 "Register in automatic mode.")); 216} 217 218void ChooseMobileNetworkHandler::HandleConnect(const ListValue* args) { 219 std::string network_id; 220 const size_t kConnectParamCount = 1; 221 if (args->GetSize() != kConnectParamCount || 222 !args->GetString(0, &network_id)) { 223 NOTREACHED(); 224 return; 225 } 226 227 GetNetworkDeviceHandler()->RegisterCellularNetwork( 228 device_path_, 229 network_id, 230 base::Bind(&base::DoNothing), 231 base::Bind(&NetworkOperationErrorCallback, 232 std::string("Register to network: ") + network_id)); 233} 234 235void ChooseMobileNetworkHandler::HandlePageReady(const ListValue* args) { 236 const size_t kConnectParamCount = 0; 237 if (args->GetSize() != kConnectParamCount) { 238 NOTREACHED(); 239 return; 240 } 241 242 if (has_pending_results_) { 243 web_ui()->CallJavascriptFunction(kJsApiShowNetworks, networks_list_); 244 networks_list_.Clear(); 245 has_pending_results_ = false; 246 } 247 is_page_ready_ = true; 248} 249 250} // namespace 251 252ChooseMobileNetworkUI::ChooseMobileNetworkUI(content::WebUI* web_ui) 253 : WebUIController(web_ui) { 254 ChooseMobileNetworkHandler* handler = new ChooseMobileNetworkHandler(); 255 web_ui->AddMessageHandler(handler); 256 // Set up the "chrome://choose-mobile-network" source. 257 Profile* profile = Profile::FromWebUI(web_ui); 258 content::WebUIDataSource::Add( 259 profile, CreateChooseMobileNetworkUIHTMLSource()); 260} 261 262} // namespace chromeos 263