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) 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); 100 virtual std::string GetMimeType(const std::string&) const { 101 return "text/html"; 102 } 103 104 private: 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 159 RegisterPageUIHTMLSource::RegisterPageUIHTMLSource() 160 : DataSource(chrome::kChromeUIRegisterPageHost, MessageLoop::current()) { 161 } 162 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 //////////////////////////////////////////////////////////////////////////////// 198 RegisterPageHandler::RegisterPageHandler() { 199 } 200 201 RegisterPageHandler::~RegisterPageHandler() { 202 } 203 204 WebUIMessageHandler* RegisterPageHandler::Attach(WebUI* web_ui) { 205 return WebUIMessageHandler::Attach(web_ui); 206 } 207 208 void RegisterPageHandler::Init() { 209 } 210 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 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 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) 256 void RegisterPageHandler::OnVersion(chromeos::VersionLoader::Handle handle, 257 std::string version) { 258 version_ = version; 259 SendUserInfo(); 260 } 261 #endif 262 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 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 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