// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/ui/webui/chromeos/register_page_ui.h" #include <string> #include "base/callback.h" #include "base/logging.h" #include "base/memory/weak_ptr.h" #include "base/string_piece.h" #include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/network_library.h" #include "chrome/browser/chromeos/customization_document.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/system_access.h" #include "chrome/browser/chromeos/version_loader.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/chrome_url_data_manager.h" #include "chrome/common/url_constants.h" #include "content/browser/browser_thread.h" #include "content/browser/tab_contents/tab_contents.h" #include "googleurl/src/gurl.h" #include "grit/browser_resources.h" #include "ui/base/resource/resource_bundle.h" namespace { // Host page JS API callback names. const char kJsCallbackGetRegistrationUrl[] = "getRegistrationUrl"; const char kJsCallbackUserInfo[] = "getUserInfo"; // Host page JS API function names. const char kJsApiSetRegistrationUrl[] = "setRegistrationUrl"; const char kJsApiSetUserInfo[] = "setUserInfo"; const char kJsApiSkipRegistration[] = "skipRegistration"; // Constant value for os_name sent in setUserInfo. const char kOSName[] = "ChromeOS"; // MachineInfo keys names. const char kMachineInfoSystemHwqual[] = "hardware_class"; const char kMachineInfoSerialNumber[] = "serial_number"; // Types of network connection. const char kConnectionEthernet[] = "ethernet"; const char kConnectionWifi[] = "wifi"; const char kConnection3g[] = "3g"; const char kUndefinedValue[] = "undefined"; // Utility function that returns string corresponding to currently active // connection type |kConnectionEthernet|kConnectionWifi|kConnection3g|. // If multiple interfaces are connected, result is based on the // priority Ethernet-Wifi-Cellular. // If there's no interface that's connected, interface that's in connecting // state is considered as the active one. // Otherwise |kUndefinedValue| is returned. #if defined(OS_CHROMEOS) static std::string GetConnectionType() { if (!chromeos::CrosLibrary::Get()->EnsureLoaded()) { LOG(ERROR) << "CrosLibrary is not loaded."; return kUndefinedValue; } chromeos::NetworkLibrary* network_lib = chromeos::CrosLibrary::Get()->GetNetworkLibrary(); if (network_lib->ethernet_connected()) return kConnectionEthernet; else if (network_lib->wifi_connected()) return kConnectionWifi; else if (network_lib->cellular_connected()) return kConnection3g; // Connection might have been lost and is in reconnecting state at this point. else if (network_lib->ethernet_connecting()) return kConnectionEthernet; else if (network_lib->wifi_connecting()) return kConnectionWifi; else if (network_lib->cellular_connecting()) return kConnection3g; else return kUndefinedValue; } #endif } // namespace class RegisterPageUIHTMLSource : public ChromeURLDataManager::DataSource { public: RegisterPageUIHTMLSource(); // Called when the network layer has requested a resource underneath // the path we registered. virtual void StartDataRequest(const std::string& path, bool is_incognito, int request_id); virtual std::string GetMimeType(const std::string&) const { return "text/html"; } private: ~RegisterPageUIHTMLSource() {} DISALLOW_COPY_AND_ASSIGN(RegisterPageUIHTMLSource); }; // The handler for Javascript messages related to the "register" view. class RegisterPageHandler : public WebUIMessageHandler, public base::SupportsWeakPtr<RegisterPageHandler> { public: RegisterPageHandler(); virtual ~RegisterPageHandler(); // Init work after Attach. void Init(); // WebUIMessageHandler implementation. virtual WebUIMessageHandler* Attach(WebUI* web_ui); virtual void RegisterMessages(); private: // Handlers for JS WebUI messages. void HandleGetRegistrationUrl(const ListValue* args); void HandleGetUserInfo(const ListValue* args); #if defined(OS_CHROMEOS) // Callback from chromeos::VersionLoader giving the version. void OnVersion(chromeos::VersionLoader::Handle handle, std::string version); #endif // Skips registration logging |error_msg| with log type ERROR. void SkipRegistration(const std::string& error_msg); // Sends message to host registration page with system/user info data. void SendUserInfo(); #if defined(OS_CHROMEOS) // Handles asynchronously loading the version. chromeos::VersionLoader version_loader_; #endif // Used to request the version. CancelableRequestConsumer version_consumer_; std::string version_; DISALLOW_COPY_AND_ASSIGN(RegisterPageHandler); }; //////////////////////////////////////////////////////////////////////////////// // // RegisterPageUIHTMLSource // //////////////////////////////////////////////////////////////////////////////// RegisterPageUIHTMLSource::RegisterPageUIHTMLSource() : DataSource(chrome::kChromeUIRegisterPageHost, MessageLoop::current()) { } void RegisterPageUIHTMLSource::StartDataRequest(const std::string& path, bool is_incognito, int request_id) { // Make sure that chrome://register is available only during // OOBE wizard lifetime and when device has not been registered yet. #if defined(OS_CHROMEOS) if (!WizardController::default_controller() || WizardController::IsDeviceRegistered()) { scoped_refptr<RefCountedBytes> empty_bytes(new RefCountedBytes); SendResponse(request_id, empty_bytes); return; } static const base::StringPiece register_html( ResourceBundle::GetSharedInstance().GetRawDataResource( IDR_HOST_REGISTRATION_PAGE_HTML)); scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); html_bytes->data.resize(register_html.size()); std::copy(register_html.begin(), register_html.end(), html_bytes->data.begin()); SendResponse(request_id, html_bytes); #else scoped_refptr<RefCountedBytes> empty_bytes(new RefCountedBytes); SendResponse(request_id, empty_bytes); #endif } //////////////////////////////////////////////////////////////////////////////// // // RegisterPageHandler // //////////////////////////////////////////////////////////////////////////////// RegisterPageHandler::RegisterPageHandler() { } RegisterPageHandler::~RegisterPageHandler() { } WebUIMessageHandler* RegisterPageHandler::Attach(WebUI* web_ui) { return WebUIMessageHandler::Attach(web_ui); } void RegisterPageHandler::Init() { } void RegisterPageHandler::RegisterMessages() { #if defined(OS_CHROMEOS) web_ui_->RegisterMessageCallback(kJsCallbackGetRegistrationUrl, NewCallback(this, &RegisterPageHandler::HandleGetRegistrationUrl)); web_ui_->RegisterMessageCallback(kJsCallbackUserInfo, NewCallback(this, &RegisterPageHandler::HandleGetUserInfo)); #endif } void RegisterPageHandler::HandleGetRegistrationUrl(const ListValue* args) { #if defined(OS_CHROMEOS) chromeos::StartupCustomizationDocument* customization = chromeos::StartupCustomizationDocument::GetInstance(); if (WizardController::default_controller() && customization->IsReady()) { const std::string& url = customization->registration_url(); VLOG(1) << "Loading registration form with URL: " << url; GURL register_url(url); if (!register_url.is_valid()) { SkipRegistration("Registration URL defined in manifest is invalid."); return; } StringValue url_value(url); web_ui_->CallJavascriptFunction(kJsApiSetRegistrationUrl, url_value); } else { SkipRegistration("Startup manifest not defined."); } #endif } void RegisterPageHandler::HandleGetUserInfo(const ListValue* args) { #if defined(OS_CHROMEOS) if (chromeos::CrosLibrary::Get()->EnsureLoaded()) { version_loader_.GetVersion( &version_consumer_, NewCallback(this, &RegisterPageHandler::OnVersion), chromeos::VersionLoader::VERSION_FULL); } else { SkipRegistration("CrosLibrary is not loaded."); } #endif } #if defined(OS_CHROMEOS) void RegisterPageHandler::OnVersion(chromeos::VersionLoader::Handle handle, std::string version) { version_ = version; SendUserInfo(); } #endif void RegisterPageHandler::SkipRegistration(const std::string& error_msg) { #if defined(OS_CHROMEOS) LOG(ERROR) << error_msg; if (WizardController::default_controller()) WizardController::default_controller()->SkipRegistration(); else web_ui_->CallJavascriptFunction(kJsApiSkipRegistration); #endif } void RegisterPageHandler::SendUserInfo() { #if defined(OS_CHROMEOS) DictionaryValue value; chromeos::SystemAccess * sys_lib = chromeos::SystemAccess::GetInstance(); // Required info. std::string system_hwqual; std::string serial_number; if (!sys_lib->GetMachineStatistic(kMachineInfoSystemHwqual, &system_hwqual) || !sys_lib->GetMachineStatistic(kMachineInfoSerialNumber, &serial_number)) { SkipRegistration("Failed to get required machine info."); return; } value.SetString("system_hwqual", system_hwqual); value.SetString("system_serial", serial_number); value.SetString("os_language", g_browser_process->GetApplicationLocale()); value.SetString("os_name", kOSName); value.SetString("os_version", version_); value.SetString("os_connection", GetConnectionType()); value.SetString("user_email", ""); // Optional info. value.SetString("user_first_name", ""); value.SetString("user_last_name", ""); web_ui_->CallJavascriptFunction(kJsApiSetUserInfo, value); #endif } //////////////////////////////////////////////////////////////////////////////// // // RegisterPageUI // //////////////////////////////////////////////////////////////////////////////// RegisterPageUI::RegisterPageUI(TabContents* contents) : WebUI(contents){ RegisterPageHandler* handler = new RegisterPageHandler(); AddMessageHandler((handler)->Attach(this)); handler->Init(); RegisterPageUIHTMLSource* html_source = new RegisterPageUIHTMLSource(); // Set up the chrome://register/ source. contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source); }