1 // Copyright (c) 2011 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/register_page_ui.h"
6
7 #include <string>
8
9 #include "base/callback.h"
10 #include "base/logging.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/string_piece.h"
13 #include "base/utf_string_conversions.h"
14 #include "base/values.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/chromeos/cros/cros_library.h"
17 #include "chrome/browser/chromeos/cros/network_library.h"
18 #include "chrome/browser/chromeos/customization_document.h"
19 #include "chrome/browser/chromeos/login/wizard_controller.h"
20 #include "chrome/browser/chromeos/system_access.h"
21 #include "chrome/browser/chromeos/version_loader.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/ui/webui/chrome_url_data_manager.h"
24 #include "chrome/common/url_constants.h"
25 #include "content/browser/browser_thread.h"
26 #include "content/browser/tab_contents/tab_contents.h"
27 #include "googleurl/src/gurl.h"
28 #include "grit/browser_resources.h"
29 #include "ui/base/resource/resource_bundle.h"
30
31 namespace {
32
33 // Host page JS API callback names.
34 const char kJsCallbackGetRegistrationUrl[] = "getRegistrationUrl";
35 const char kJsCallbackUserInfo[] = "getUserInfo";
36
37 // Host page JS API function names.
38 const char kJsApiSetRegistrationUrl[] = "setRegistrationUrl";
39 const char kJsApiSetUserInfo[] = "setUserInfo";
40 const char kJsApiSkipRegistration[] = "skipRegistration";
41
42 // Constant value for os_name sent in setUserInfo.
43 const char kOSName[] = "ChromeOS";
44
45 // MachineInfo keys names.
46 const char kMachineInfoSystemHwqual[] = "hardware_class";
47 const char kMachineInfoSerialNumber[] = "serial_number";
48
49 // Types of network connection.
50 const char kConnectionEthernet[] = "ethernet";
51 const char kConnectionWifi[] = "wifi";
52 const char kConnection3g[] = "3g";
53 const char kUndefinedValue[] = "undefined";
54
55 // Utility function that returns string corresponding to currently active
56 // connection type |kConnectionEthernet|kConnectionWifi|kConnection3g|.
57 // If multiple interfaces are connected, result is based on the
58 // priority Ethernet-Wifi-Cellular.
59 // If there's no interface that's connected, interface that's in connecting
60 // state is considered as the active one.
61 // Otherwise |kUndefinedValue| is returned.
62 #if defined(OS_CHROMEOS)
GetConnectionType()63 static std::string GetConnectionType() {
64 if (!chromeos::CrosLibrary::Get()->EnsureLoaded()) {
65 LOG(ERROR) << "CrosLibrary is not loaded.";
66 return kUndefinedValue;
67 }
68
69 chromeos::NetworkLibrary* network_lib =
70 chromeos::CrosLibrary::Get()->GetNetworkLibrary();
71 if (network_lib->ethernet_connected())
72 return kConnectionEthernet;
73 else if (network_lib->wifi_connected())
74 return kConnectionWifi;
75 else if (network_lib->cellular_connected())
76 return kConnection3g;
77 // Connection might have been lost and is in reconnecting state at this point.
78 else if (network_lib->ethernet_connecting())
79 return kConnectionEthernet;
80 else if (network_lib->wifi_connecting())
81 return kConnectionWifi;
82 else if (network_lib->cellular_connecting())
83 return kConnection3g;
84 else
85 return kUndefinedValue;
86 }
87 #endif
88
89 } // namespace
90
91 class RegisterPageUIHTMLSource : public ChromeURLDataManager::DataSource {
92 public:
93 RegisterPageUIHTMLSource();
94
95 // Called when the network layer has requested a resource underneath
96 // the path we registered.
97 virtual void StartDataRequest(const std::string& path,
98 bool is_incognito,
99 int request_id);
GetMimeType(const std::string &) const100 virtual std::string GetMimeType(const std::string&) const {
101 return "text/html";
102 }
103
104 private:
~RegisterPageUIHTMLSource()105 ~RegisterPageUIHTMLSource() {}
106
107 DISALLOW_COPY_AND_ASSIGN(RegisterPageUIHTMLSource);
108 };
109
110 // The handler for Javascript messages related to the "register" view.
111 class RegisterPageHandler : public WebUIMessageHandler,
112 public base::SupportsWeakPtr<RegisterPageHandler> {
113 public:
114 RegisterPageHandler();
115 virtual ~RegisterPageHandler();
116
117 // Init work after Attach.
118 void Init();
119
120 // WebUIMessageHandler implementation.
121 virtual WebUIMessageHandler* Attach(WebUI* web_ui);
122 virtual void RegisterMessages();
123
124 private:
125 // Handlers for JS WebUI messages.
126 void HandleGetRegistrationUrl(const ListValue* args);
127 void HandleGetUserInfo(const ListValue* args);
128
129 #if defined(OS_CHROMEOS)
130 // Callback from chromeos::VersionLoader giving the version.
131 void OnVersion(chromeos::VersionLoader::Handle handle, std::string version);
132 #endif
133
134 // Skips registration logging |error_msg| with log type ERROR.
135 void SkipRegistration(const std::string& error_msg);
136
137 // Sends message to host registration page with system/user info data.
138 void SendUserInfo();
139
140 #if defined(OS_CHROMEOS)
141 // Handles asynchronously loading the version.
142 chromeos::VersionLoader version_loader_;
143 #endif
144
145 // Used to request the version.
146 CancelableRequestConsumer version_consumer_;
147
148 std::string version_;
149
150 DISALLOW_COPY_AND_ASSIGN(RegisterPageHandler);
151 };
152
153 ////////////////////////////////////////////////////////////////////////////////
154 //
155 // RegisterPageUIHTMLSource
156 //
157 ////////////////////////////////////////////////////////////////////////////////
158
RegisterPageUIHTMLSource()159 RegisterPageUIHTMLSource::RegisterPageUIHTMLSource()
160 : DataSource(chrome::kChromeUIRegisterPageHost, MessageLoop::current()) {
161 }
162
StartDataRequest(const std::string & path,bool is_incognito,int request_id)163 void RegisterPageUIHTMLSource::StartDataRequest(const std::string& path,
164 bool is_incognito,
165 int request_id) {
166 // Make sure that chrome://register is available only during
167 // OOBE wizard lifetime and when device has not been registered yet.
168 #if defined(OS_CHROMEOS)
169 if (!WizardController::default_controller() ||
170 WizardController::IsDeviceRegistered()) {
171 scoped_refptr<RefCountedBytes> empty_bytes(new RefCountedBytes);
172 SendResponse(request_id, empty_bytes);
173 return;
174 }
175
176 static const base::StringPiece register_html(
177 ResourceBundle::GetSharedInstance().GetRawDataResource(
178 IDR_HOST_REGISTRATION_PAGE_HTML));
179
180 scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
181 html_bytes->data.resize(register_html.size());
182 std::copy(register_html.begin(),
183 register_html.end(),
184 html_bytes->data.begin());
185
186 SendResponse(request_id, html_bytes);
187 #else
188 scoped_refptr<RefCountedBytes> empty_bytes(new RefCountedBytes);
189 SendResponse(request_id, empty_bytes);
190 #endif
191 }
192
193 ////////////////////////////////////////////////////////////////////////////////
194 //
195 // RegisterPageHandler
196 //
197 ////////////////////////////////////////////////////////////////////////////////
RegisterPageHandler()198 RegisterPageHandler::RegisterPageHandler() {
199 }
200
~RegisterPageHandler()201 RegisterPageHandler::~RegisterPageHandler() {
202 }
203
Attach(WebUI * web_ui)204 WebUIMessageHandler* RegisterPageHandler::Attach(WebUI* web_ui) {
205 return WebUIMessageHandler::Attach(web_ui);
206 }
207
Init()208 void RegisterPageHandler::Init() {
209 }
210
RegisterMessages()211 void RegisterPageHandler::RegisterMessages() {
212 #if defined(OS_CHROMEOS)
213 web_ui_->RegisterMessageCallback(kJsCallbackGetRegistrationUrl,
214 NewCallback(this, &RegisterPageHandler::HandleGetRegistrationUrl));
215 web_ui_->RegisterMessageCallback(kJsCallbackUserInfo,
216 NewCallback(this, &RegisterPageHandler::HandleGetUserInfo));
217 #endif
218 }
219
HandleGetRegistrationUrl(const ListValue * args)220 void RegisterPageHandler::HandleGetRegistrationUrl(const ListValue* args) {
221 #if defined(OS_CHROMEOS)
222 chromeos::StartupCustomizationDocument* customization =
223 chromeos::StartupCustomizationDocument::GetInstance();
224 if (WizardController::default_controller() &&
225 customization->IsReady()) {
226 const std::string& url = customization->registration_url();
227 VLOG(1) << "Loading registration form with URL: " << url;
228 GURL register_url(url);
229 if (!register_url.is_valid()) {
230 SkipRegistration("Registration URL defined in manifest is invalid.");
231 return;
232 }
233 StringValue url_value(url);
234 web_ui_->CallJavascriptFunction(kJsApiSetRegistrationUrl, url_value);
235 } else {
236 SkipRegistration("Startup manifest not defined.");
237 }
238 #endif
239 }
240
HandleGetUserInfo(const ListValue * args)241 void RegisterPageHandler::HandleGetUserInfo(const ListValue* args) {
242 #if defined(OS_CHROMEOS)
243 if (chromeos::CrosLibrary::Get()->EnsureLoaded()) {
244 version_loader_.GetVersion(
245 &version_consumer_,
246 NewCallback(this,
247 &RegisterPageHandler::OnVersion),
248 chromeos::VersionLoader::VERSION_FULL);
249 } else {
250 SkipRegistration("CrosLibrary is not loaded.");
251 }
252 #endif
253 }
254
255 #if defined(OS_CHROMEOS)
OnVersion(chromeos::VersionLoader::Handle handle,std::string version)256 void RegisterPageHandler::OnVersion(chromeos::VersionLoader::Handle handle,
257 std::string version) {
258 version_ = version;
259 SendUserInfo();
260 }
261 #endif
262
SkipRegistration(const std::string & error_msg)263 void RegisterPageHandler::SkipRegistration(const std::string& error_msg) {
264 #if defined(OS_CHROMEOS)
265 LOG(ERROR) << error_msg;
266 if (WizardController::default_controller())
267 WizardController::default_controller()->SkipRegistration();
268 else
269 web_ui_->CallJavascriptFunction(kJsApiSkipRegistration);
270 #endif
271 }
272
SendUserInfo()273 void RegisterPageHandler::SendUserInfo() {
274 #if defined(OS_CHROMEOS)
275 DictionaryValue value;
276
277 chromeos::SystemAccess * sys_lib =
278 chromeos::SystemAccess::GetInstance();
279
280 // Required info.
281 std::string system_hwqual;
282 std::string serial_number;
283 if (!sys_lib->GetMachineStatistic(kMachineInfoSystemHwqual, &system_hwqual) ||
284 !sys_lib->GetMachineStatistic(kMachineInfoSerialNumber, &serial_number)) {
285 SkipRegistration("Failed to get required machine info.");
286 return;
287 }
288 value.SetString("system_hwqual", system_hwqual);
289 value.SetString("system_serial", serial_number);
290 value.SetString("os_language", g_browser_process->GetApplicationLocale());
291 value.SetString("os_name", kOSName);
292 value.SetString("os_version", version_);
293 value.SetString("os_connection", GetConnectionType());
294 value.SetString("user_email", "");
295
296 // Optional info.
297 value.SetString("user_first_name", "");
298 value.SetString("user_last_name", "");
299
300 web_ui_->CallJavascriptFunction(kJsApiSetUserInfo, value);
301 #endif
302 }
303
304 ////////////////////////////////////////////////////////////////////////////////
305 //
306 // RegisterPageUI
307 //
308 ////////////////////////////////////////////////////////////////////////////////
309
RegisterPageUI(TabContents * contents)310 RegisterPageUI::RegisterPageUI(TabContents* contents) : WebUI(contents){
311 RegisterPageHandler* handler = new RegisterPageHandler();
312 AddMessageHandler((handler)->Attach(this));
313 handler->Init();
314 RegisterPageUIHTMLSource* html_source = new RegisterPageUIHTMLSource();
315
316 // Set up the chrome://register/ source.
317 contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
318 }
319