e1467f7dedf3860736eef65339ab34ccc8b9665e
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / chromeos / choose_mobile_network_ui.cc
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 "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"
31
32 using content::WebContents;
33 using content::WebUIMessageHandler;
34
35 namespace chromeos {
36
37 namespace {
38
39 // JS API callbacks names.
40 const char kJsApiCancel[] = "cancel";
41 const char kJsApiConnect[] = "connect";
42 const char kJsApiPageReady[] = "pageReady";
43
44 // Page JS API function names.
45 const char kJsApiShowNetworks[] = "mobile.ChooseNetwork.showNetworks";
46 const char kJsApiShowScanning[] = "mobile.ChooseNetwork.showScanning";
47
48 // Network properties.
49 const char kNetworkIdProperty[] = "networkId";
50 const char kOperatorNameProperty[] = "operatorName";
51 const char kStatusProperty[] = "status";
52 const char kTechnologyProperty[] = "technology";
53
54 content::WebUIDataSource* CreateChooseMobileNetworkUIHTMLSource() {
55   content::WebUIDataSource* source = content::WebUIDataSource::Create(
56       chrome::kChromeUIChooseMobileNetworkHost);
57
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);
68
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);
74   return source;
75 }
76
77 chromeos::NetworkDeviceHandler* GetNetworkDeviceHandler() {
78   return chromeos::NetworkHandler::Get()->network_device_handler();
79 }
80
81 chromeos::NetworkStateHandler* GetNetworkStateHandler() {
82   return chromeos::NetworkHandler::Get()->network_state_handler();
83 }
84
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);
90 }
91
92 class ChooseMobileNetworkHandler
93     : public WebUIMessageHandler,
94       public NetworkStateHandlerObserver {
95  public:
96   ChooseMobileNetworkHandler();
97   virtual ~ChooseMobileNetworkHandler();
98
99   // WebUIMessageHandler implementation.
100   virtual void RegisterMessages() OVERRIDE;
101
102   // NetworkStateHandlerObserver implementation.
103   virtual void DeviceListChanged() OVERRIDE;
104
105  private:
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);
110
111   std::string device_path_;
112   base::ListValue networks_list_;
113   bool is_page_ready_;
114   bool has_pending_results_;
115
116   DISALLOW_COPY_AND_ASSIGN(ChooseMobileNetworkHandler);
117 };
118
119 // ChooseMobileNetworkHandler implementation.
120
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());
127   if (!cellular) {
128     NET_LOG_ERROR(
129         "A cellular device is not available.",
130         "Cannot initiate a cellular network scan without a cellular device.");
131     return;
132   }
133   handler->AddObserver(this, FROM_HERE);
134   device_path_ = cellular->path();
135   GetNetworkDeviceHandler()->ProposeScan(
136       device_path_,
137       base::Bind(&base::DoNothing),
138       base::Bind(&NetworkOperationErrorCallback, "ProposeScan"));
139 }
140
141 ChooseMobileNetworkHandler::~ChooseMobileNetworkHandler() {
142   GetNetworkStateHandler()->RemoveObserver(this, FROM_HERE);
143 }
144
145 void ChooseMobileNetworkHandler::RegisterMessages() {
146   web_ui()->RegisterMessageCallback(
147       kJsApiCancel,
148       base::Bind(&ChooseMobileNetworkHandler::HandleCancel,
149                  base::Unretained(this)));
150   web_ui()->RegisterMessageCallback(
151       kJsApiConnect,
152       base::Bind(&ChooseMobileNetworkHandler::HandleConnect,
153                  base::Unretained(this)));
154   web_ui()->RegisterMessageCallback(
155       kJsApiPageReady,
156       base::Bind(&ChooseMobileNetworkHandler::HandlePageReady,
157                  base::Unretained(this)));
158 }
159
160 void ChooseMobileNetworkHandler::DeviceListChanged() {
161   const DeviceState* cellular = GetNetworkStateHandler()->GetDeviceState(
162       device_path_);
163   networks_list_.Clear();
164   if (!cellular) {
165     LOG(WARNING) << "Cellular device with path '" << device_path_
166                  << "' disappeared.";
167     return;
168   }
169   if (cellular->scanning()) {
170     NET_LOG_EVENT("ChooseMobileNetwork", "Device is scanning for networks.");
171     web_ui()->CallJavascriptFunction(kJsApiShowScanning);
172     return;
173   }
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
182     // network in UI.
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);
190       else
191         network->SetString(kOperatorNameProperty, it->network_id);
192       network->SetString(kStatusProperty, it->status);
193       network->SetString(kTechnologyProperty, it->technology);
194       networks_list_.Append(network);
195     }
196   }
197   if (is_page_ready_) {
198     web_ui()->CallJavascriptFunction(kJsApiShowNetworks, networks_list_);
199     networks_list_.Clear();
200     has_pending_results_ = false;
201   } else {
202     has_pending_results_ = true;
203   }
204 }
205
206 void ChooseMobileNetworkHandler::HandleCancel(const base::ListValue* args) {
207   const size_t kConnectParamCount = 0;
208   if (args->GetSize() != kConnectParamCount) {
209     NOTREACHED();
210     return;
211   }
212
213   // Switch to automatic mode.
214   GetNetworkDeviceHandler()->RegisterCellularNetwork(
215       device_path_,
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."));
220 }
221
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)) {
227     NOTREACHED();
228     return;
229   }
230
231   GetNetworkDeviceHandler()->RegisterCellularNetwork(
232       device_path_,
233       network_id,
234       base::Bind(&base::DoNothing),
235       base::Bind(&NetworkOperationErrorCallback,
236                  std::string("Register to network: ") + network_id));
237 }
238
239 void ChooseMobileNetworkHandler::HandlePageReady(const base::ListValue* args) {
240   const size_t kConnectParamCount = 0;
241   if (args->GetSize() != kConnectParamCount) {
242     NOTREACHED();
243     return;
244   }
245
246   if (has_pending_results_) {
247     web_ui()->CallJavascriptFunction(kJsApiShowNetworks, networks_list_);
248     networks_list_.Clear();
249     has_pending_results_ = false;
250   }
251   is_page_ready_ = true;
252 }
253
254 }  // namespace
255
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());
264 }
265
266 }  // namespace chromeos